- inspired by https://thixalongmy.haugiang.gov.vn/media/1175/clean_code.pdf
- inspired by https://12factor.net/
- follow standard conventions and the conventions already laid out in the codebase you are working in
- keep it simple - don't try to be clever
- be consistent - if you do something a specific way, always do it that way
- boy scout rule - leave the campground cleaner than you found it
- always find the root cause - always look for the root cause of a problem. don't fix things by slapping fixes in different places till things work. break it down and solve the problem in increments
-
choose descriptive and unambiguous names
Incorrect:
form = CreateNoteForm({}})
Correct:
create_note_form = CreateNoteForm({}})
-
use pronounceable and searchable names
Incorrect:
tmstmp = time.time()
Correct:
time_stamp = time.time()
-
no single letters as variables unless it's for things like the index of an iterator or actual geometry
Incorrect:
n = datetime.datetime.now() ... for n in Notes.objects.all(): n.do_something()
Correct:
now = datetime.datetime.now() ... for note in Notes.objects.all(): note.do_something ... for i in range(len(items)): pass ... @dataclass class Point: x: int y: int
-
replace magic numbers with named constants
Incorrect:
if len(password) < 8: raise Exception("Password must be at least 8 characters.")
Correct:
MINIMUM_PASSWORD_LENGTH = 8 if len(password) < MINIMUM_PASSWORD_LENGTH: raise Exception("Password must be at least 8 characters.")
-
avoid encoding data in the variable name. don't append or prefix type information
Incorrect:
point_str = "(1, 3)"
Correct:
point = "1, 3" point = Point(point)
-
do one thing and do it well
-
use descriptive names
Incorrect:
def connect(): pass
Correct:
def create_database_connection(): pass
-
prefer fewer arguments. if you have a lot of arguments, it might be a sign you need to refactor your function
-
ideally, no side effects. this makes things much easier to test
-
don't use flag arguments. split method into several independent methods can be called from the client without the flag
-
always try to explain yourself in code - if you find yourself writing a comment for some block of code, see if you can instead make the code easier to understand
-
prefer doc comments
Incorrect:
# create a note def create_note(title, content): # create note object note - Notes.objects.create(title, content) # set created_at note.created_at = now() # save note note.save()
Correct:
def create_note(title, content): """Creates note object and sets `created_at` to the current time. note - Notes.objects.create(title, content) note.created_at = now() note.save()
-
don't be redundant
Incorrect:
# create a note note = Notes.objects.create(...)
-
don't add obvious noise
-
don't use closing brace comments
Incorrect:
if some_condition is True: ... # end if some_condition
-
don't comment out code, just remove it. this is why we have git.
-
use as an explanation of intent - doc comments are great for explaining the intent of a class or function
-
use as clarification of code - sometimes programmers do have to write code that is confusing by its very nature. it's fine to have a comment clarifying the code in this case
-
use as warning of consequence - let the next programmer know what might happen if something is changed if it's not immediately obvious from the code
- rigidity. the software is difficult to change. a small change causes a cascade of subsequent changes
- fragility. the software breaks in many places due to a single change
- immobility. you cannot reuse parts of the code in other projects because of involved risks and high effort
- needless complexity
- needless repetition
- opacity. the code is hard to understand