I find methods/functions decomposed into three parts really satisfying. Consider a typical xUnit test:
def test_grants_new_role # setup user = make_user new_role = make_new_role # behavior under test user.add_role(new_role) # assert results assert_equal [new_role], user.roles end
Lately I’ve been structuring Rails controller similarly:
def create # Extract inputs/parameters from HTTP request person_params = params.require(:person).permit(:name, :age) # Invoke behavior encapsulated in a Plain(ish) Ruby object somewhere user = UserService.create_user(person_params) # Check the result and make some HTTP output if user.persisted? redirect_to user_path(user.id) else @user = user render :new end end
Clojure even has the
let form which encourages this style:
; annotated from clj-http ; https://github.com/dakrone/clj-http/blob/master/src/clj_http/util.clj (defn gzip "Returns a gzip'd version of the given byte array." [b] (when b ; set the table (let [baos (ByteArrayOutputStream.) gos (GZIPOutputStream. baos)] ; do the work and clean up (IOUtils/copy (ByteArrayInputStream. b) gos) (.close gos) ; produce a result (.toByteArray baos))))
I don’t think there’s anything inherently wrong if a method or function isn’t organized this way. But when I read code structured this way, it feels less like a bunch of random logic and more like a cohesive unit that someone put time into thinking through how someone might try to understand it later. The Rule of Three rules everything around us.