Intro
- wtfs per minute
- craftsmanship - knowledge and work
- princples patterns and practices
Chapter 1: Clean code
- we will always have code
- specifying requirements is programming
- the specification is code
- sure there will be abstractions, but we will always need code
- Bad code
- wading - slowed down by bad code
- ambiguity of purpose
- muddled intent
- room for speculation
- Clean code
- focused
- crisp on writers intent
- easy for other ppl to enhance it
- no duplication
- method - says what it does
- impl - says how it is done
- wrap particular implementation in a more abstract method or class
- impl - says how it is done
- total cost of owning a mess
- asymptotically lowers productivity
- each change requires untangling and understanding
- a broken window in an apt causes other ppl to not care and make a mess
- doing 1 thing
- object or a method should just focus on 1 thing
- Ron Jeffries
- no duplication
- one thing
- expressiveness
- tiny abstractions
- we read old code 10x more than writing during writing. so we want old code to be easy to read -> easy to read = easy to write
Chapter 2: Meaningful Names
- intention-revealing names
- never distinguish 2 things by using non-distinguishing name
- ex: doing account vs theAccount (bc cant have duplicates in scope)
- if there's a different object or function, explicitly describe the intention / difference
- length of name can correspond to size of scope
- one letter name is OK if it's a tiny scope
- make things searchable
- ex: using a const instead of a magic number
- avoid prefix, use class: using prefix is ok when adding context of a larger structure BUT using class is better
- prefix ex: addressState, addressFirstName, etc
- class ex: Address.state
- add details from page 29
- split large functions with lots of repeat variable usage -> to a class with small functions
Chapter 3: Functions
- SMALL SMALL SMALL
- DO JUST ONE THING
- how to classify as just 1 thing -> 1 layer of abstraction
- to "TO" test -> "TO {function name} we do x, y, z"
- another way to tell -> if you can extract small function and it's not just a re-statement
- another way to tell -> if you divide into sections
- combine with meaningful and intention-revealing names
- split large functions -> a class (? when to split to class vs smaller methods)
- blocks within
if,else,whileshould be 1 line long (functional call) - results in documentation in the form of being descriptive
- max indent level - 1 or 2 arguments
- max arguments - 3 maxxx
- 0 or 1 or 2
- 0 - ideal
- make it part of the class, use class variables
- 1 - ok for taking in input
- 2 - ok for related to single component (ex: an xy point)
- more arguments, more complicated tests, more cognitive load, probably doing more than 1 thing
- if you need more than 1, mostly use an object
- don't use arguments for outputs
- don't use arguments for flags - means function is doing more than 1 thing naming
- name should describe intent (and intent of arguments)
- ex: assertExpectedEqualsActual(expected, equals)
- consistent logic
- DRY
- no side effects
- command and query separation - should either do something or answer, not both
- bad example: public boolean set(String attribute, String value) returns true when successful is confusing
- if(set("username", "unclebob)) is confusing. is it true if previously set, successfully set? etc is set adjective or verb error handling
- bad example: public boolean set(String attribute, String value) returns true when successful is confusing
- use exceptions instead of returning error code
- error handling IS 1 thing
- have 1 dedicated method for try catching logic
- and extract try and catch logic to another function dependency magnet
- ex: error code class that is used everywhere. change to this requires re-compile of tons of classes
- instead, use something that is derivatives (oops), like exception classes
Chapter 4: Comments
- comments at best are evil
- comments compensate for our failure to express in code
Chapter 5: Formatting
- use a consistent format file
- newspaper method - top to bottom, order of detail (high level to lower level details)
- use lines to separate concepts
- vertical density - more for close relation
- vertical distance - separate concepts/relations structure
- closely related concepts should be in the same file variables
- declaration should be vertically close as possible to their usage
- instance variables used by many methods - put at the top functions
- dependent functions should be vertically close. caller should be above callee.
- dependencies flows downwards
- for constants input into a function, makes more sense to have it as the input where it makes it easy to read and quickly understand what that method will do instead of hiding it in a lower level method
Chapter 6: Objects and Data Structures
pg 93 handling state throughout sessions in stateless microsystem architecture using AgentThread
add deterministic algorithms to agentic system to increase robustness
middleware for token calc
chatt history + summary agent