Skip to content
academia.sh

Course Beginner

Clean Code

By the end of this course

Start course

01

Naming and Structure

Measuring intent-revealing names at the call site, translating comments into code, the single level of abstraction rule, the cost of code format on reading diffs, computing cyclomatic complexity, and choosing between a conditional chain, a lookup table, and polymorphism.

  1. 01 Meaningful Names Treating naming as a measurable design decision: counting opaque arguments at the call site in a shortened and an intent-revealing version of the same shipment fee calculation, deriving how many candidate words an abbreviation could resolve to, and the relationship between name length and the scope a name lives in.
  2. 02 Names Instead of Comments Measuring the mismatch that follows from a comment being uncompiled, unchecked text: auditing whether the number claims in the comments of a shipment fee module match their counterparts in the code, the refactoring that turns claims into names, and the kinds of comments that cannot be turned into a name.
  3. 03 Small Functions and Classes Pulling the splitting measure out of line count and tying it to the single level of abstraction rule: an analyzer that counts how many separate abstraction levels a body carries vocabulary from, comparing level span across two versions of fee line generation, and applying the same measure to classes.
  4. 04 Indentation and Code Formatting Taking code format out of the realm of style and measuring it by diff cost: the diff lines produced by the same content in two indentation schemes, the diff line counts the same revision produces in an aligned and a plain form of the tariff table, and separating out the diff lines that carry no content.
  5. 05 Reducing Cyclomatic Complexity Measuring and reducing the number of branches: writing a measurer that counts decision points, comparing cyclomatic complexity between a nested and a simplified version of the fee calculation, and moving branching into data with guard clause and lookup table transformations.
  6. 06 Choosing the Right Structure Writing three versions of the same behavior with a conditional chain, a lookup table, and polymorphism, and tying the choice to a measure: the number of files and lines touched when a new tariff type is added, how many places a type name appears, and the cost of a type carrying its own state.

02

Interface and Data Decisions

Designing what a function tells the outside world: making the null value visible in the contract, splitting a boolean flag parameter into two separate functions, the principle of least visibility, organizing code by reason to change into actors, and doing the same job the same way throughout a project.

  1. 01 Do Not Pass Null Measuring how visible a null value is in a contract: how many calls after a null-returning chain an error surfaces, how that same distance drops to zero in a version that shows the missing case in the result type, and replacing signatures that pass null as an argument with an empty collection.
  2. 02 Boolean Flag Parameters Measuring the cost of parameters that carry a boolean value through testing: comparing, with node --test, the number of tests needed to cover the branches of a single function with two flags against two split functions, the number of branches the flag opens in the body, and the opaque arguments at the call site.
  3. 03 Scope and Visibility Measuring the principle of least visibility with an import graph: comparing the public surface, the number of dependent files, the unused export surface, and the number of freely changeable names between two versions of the same fee package — one that exports every name and one that exports only two.
  4. 04 Organizing Code by Actor Measuring the grouping of code by reason to change instead of by technical layer: how many actors' decisions are defined in a file, how many files each actor spans, and how many files a single accounting change touches, compared across two layouts of the same fee package.
  5. 05 Consistency Measuring whether the same job is done the same way throughout a project: a scan that finds the number of forms in a package that does three separate jobs in three separate ways, repeating the measurement after unification, and counting the changes that merging forms causes in outputs and error behavior.

03

Simplicity Principles

Separating knowledge duplication from incidental similarity, evolving a design in small steps, the measured cost of premature generalization, the extract–move–rename refactoring techniques, and securing behavior preservation with tests.

  1. 01 Do Not Repeat Yourself Separating two pieces of code that merely happen to look alike from information that genuinely lives in one place, counting how many tier boundaries diverge, and measuring the wrong abstraction that merging two call sites into one function produces by its flag count.
  2. 02 Keep It Simple and Refactor Often Meeting the same fee requirement with a solution designed in one step and a solution that evolves through five small steps, measuring the lines changed at each step, and comparing the suspect zone a red test points to.
  3. 03 You Are Not Going to Need It Measuring an extension point and a configuration layer added to the fee calculation today by their decision-point count, branch coverage, and unexercised-path count; showing with a failing run that the incoming requirement does not fit that structure, and discarding the generalization.
  4. 04 Refactoring Techniques Applying the extract, move, and rename techniques to the fee library through their intermediate steps; taking a test run after every step and measuring the steps by coverage, file count, and name-occurrence count.
  5. 05 Refactoring Under Test Finding, through a scan, behavior that silently changed in an extraction step done without a test; measuring a six-test suite's catching power with mutations; and having the strengthened suite turn that same step red.

Start typing to search.

↑↓ Esc navigate · open · close