This might sound ridiculous, but I'm subject to anthropomorphism when coding. I see little beings (objects) in a company (codebase) only trying to do their job the best they can. Here is a weird suggestion: envision objects as colleagues and understand how they would collaborate.
self
Just like you would try to understand another's point of view in an argument or debate, try to understand the current context: self
of a method. Zoom in the method and guess whether the collaboration would make sense and work in real life.
In this example from to press or not to press the vrosswalk button, put yourself in the Service and Worker's shoes.
# 1. DIY section
module BookSalesService
def schedule_with_two_flags(book)
# Check if sales are being calculated right now
return unless book.sales_enqueued_at > book.sales_calculated_at
book.update(sales_enqueued_at: Time.current)
BookSalesWorker.perform_later(book.id)
end
end
class BookSalesWorker < ActiveJob::Base
def perform(book_id)
crunch_some_numbers(book_id)
upload_to_s3
# New adition
book.update(sales_calculated_at: Time.current)
end
# ...
end
As BookSalesService
, I have good intentions. I aim to save time and prevent unnecessary work for my colleague by implementing a two-step process. I have many responsibilities, so a comment explaining this part of the process is necessary.
As BookSalesWorker
, I might feel slighted. Am I too dumb to check whether the book had its sales numbers calculated recently? Why are we even doing this two step check, it's inefficient.
At work, would you rather be asked to solve a problem or monkey code someone else's solution word for word? A leader would confidently give you a task, knowing you can solve it independently. A micromanager will review your code and ask for changes until it matches the solution they have in mind.
In this example BookSalesService
trusts BookSalesWorker
to perform the task appropriately and also be performant if needed.
module BookSalesService
def schedule_with_two_flags(book)
BookSalesWorker.perform_later(book.id)
end
end
class BookSalesWorker < ActiveJob::Base
around_enqueue do |job, block|
book = Book.find(job.arguments.first)
if book.sales_enqueued_at < book.sales_calculated_at
book.update(sales_enqueued_at: Time.current)
block.call
book.update(sales_calculated_at: Time.current)
end
end
def perform(book_id)
crunch_some_numbers(book_id)
upload_to_s3
end
end
I have no control over the leadership strategies of my actual manager, but I can be a great leader and design these little objects so that collaboration is healthy in their world.
Do you write code like a leader or a micromanager?