{"id":5153,"date":"2025-02-11T18:33:23","date_gmt":"2025-02-11T16:33:23","guid":{"rendered":"https:\/\/adrhc.go.ro\/blog\/?p=5153"},"modified":"2025-03-02T19:02:01","modified_gmt":"2025-03-02T17:02:01","slug":"lambda-expressions-with-many-lines","status":"publish","type":"post","link":"https:\/\/adrhc.go.ro\/blog\/lambda-expressions-with-many-lines\/","title":{"rendered":"Lambda expressions with many lines"},"content":{"rendered":"<p>Recently, I was writing a test method similar to this:<\/p>\n<pre class=\"brush: java;toolbar: false;auto-links: true\">\r\n\/**\r\n * SOME_FEATURE is a constant that identifies a feature the application provides if enabled\r\n *\/\r\nvoid transferMoneyTest() {\r\n\twithEnabledFeature(SOME_FEATURE, () -> {\r\n\t\t\/\/ line one of the test method\r\n\t\t\/\/ line two of the test method\r\n\t\t\/\/ line three of the test method\r\n\t\t\/\/ line four of the test method\r\n\t\t\/\/ line five of the test method\r\n\t\t\/\/ line six of the test method\r\n\t\t\/\/ line seven of the test method\r\n\t});\r\n}\r\n<\/pre>\n<p>One of my colleagues pointed out that it is a best practice to place lambda code in a distinct method when its size exceeds a certain threshold (e.g., 2 or 3 lines). Hmm, I thought to myself, he is right, but there are exceptions &#8211; and this is one of them.<\/p>\n<p>But why is that an exception? Well, let&#8217;s see other similar examples:<\/p>\n<pre class=\"brush: java;toolbar: false;auto-links: true\">\r\n\/**\r\n * \"transactional\" method provides the ACID transaction context for the lambda \r\n * execution (is the equivalent of e.g., @Transactional from Spring Framework)\r\n *\/\r\npublic void transferMoney() {\r\n\ttransactional(() -> {\r\n\t\t\/\/ line one of the method's implementation\r\n\t\t\/\/ line two of the method's implementation\r\n\t\t\/\/ line three of the method's implementation\r\n\t\t\/\/ line four of the method's implementation\r\n\t\t\/\/ line five of the method's implementation\r\n\t\t\/\/ line six of the method's implementation\r\n\t\t\/\/ line seven of the method's implementation\r\n\t});\r\n}\r\n\r\n\/**\r\n * \"preAuthorize\" method provides the security context for the lambda \r\n * execution (is the equivalent of e.g., @PreAuthorize from Spring Security)\r\n *\/\r\npublic void transferMoney() {\r\n\tpreAuthorize(\"hasAuthority('permission:write')\", () -> {\r\n\t\t\/\/ line one of the method's implementation\r\n\t\t\/\/ line two of the method's implementation\r\n\t\t\/\/ line three of the method's implementation\r\n\t\t\/\/ line four of the method's implementation\r\n\t\t\/\/ line five of the method's implementation\r\n\t\t\/\/ line six of the method's implementation\r\n\t\t\/\/ line seven of the method's implementation\r\n\t});\r\n}\r\n\r\n\/**\r\n * Let's suppose it doesn't make sense to use *synchronized* at the method level.\r\n *\/\r\npublic void transferMoney() {\r\n\tsynchronized (merchant) {\r\n\t\t\/\/ line one of the method's implementation\r\n\t\t\/\/ line two of the method's implementation\r\n\t\t\/\/ line three of the method's implementation\r\n\t\t\/\/ line four of the method's implementation\r\n\t\t\/\/ line five of the method's implementation\r\n\t\t\/\/ line six of the method's implementation\r\n\t\t\/\/ line seven of the method's implementation\r\n\t});\r\n}\r\n<\/pre>\n<p>All the above examples show some code blocks executed in a particular *context*.<br \/>\nWould the code be more readable if one took the below approach instead of a lambda expression?<\/p>\n<pre class=\"brush: java;toolbar: false;auto-links: true\">\r\npublic void transferMoney() {\r\n\ttransactional(doTransferMoney);\r\n}\r\n\/\/ ...\r\n\/\/ a\r\n\/\/ bunch\r\n\/\/ of \r\n\/\/ other \r\n\/\/ public, \r\n\/\/ protected, \r\n\/\/ and \r\n\/\/ private \r\n\/\/ methods \r\n\/\/ go \r\n\/\/ here\r\n\/\/ (i.e., there's a big distance between transferMoney and doTransferMoney)\r\n\/\/ ...\r\nprivate void doTransferMoney() {\r\n\t\/\/ line one of the method's implementation\r\n\t\/\/ line two of the method's implementation\r\n\t\/\/ line three of the method's implementation\r\n\t\/\/ line four of the method's implementation\r\n\t\/\/ line five of the method's implementation\r\n\t\/\/ line six of the method's implementation\r\n\t\/\/ line seven of the method's implementation\r\n}\r\n<\/pre>\n<p>Well, the transferMoney is much shorter and hence easier to read; the problem though is with *what* is left to read:<br \/>\nthe user reads a method meaning &#8220;transfer money&#8221; (i.e., transferMoney) which does &#8220;transfer money&#8221; (i.e., doTransferMoney) in a transactional fashion (well, at least he learns something about the *execution context*).  <\/p>\n<p>This is silly; in the above situations, I would rather keep the doTransferMoney content in transferMoney method because it&#8217;s easy to spot the distinction between the *execution context* and the *behaviour* implementation; moving the *behaviour* in another method brings no benefit.<\/p>\n<p>This does not invalidate the rule of thumb that a lambda expression larger than 2-3 lines is best to be moved to a distinct method. In most situations, the *behaviour* is mixed with the lambda expressions hence the reader has to collapse the lambda expression to see the rest (i.e., the *behaviour*). It&#8217;s not the same for transferMoneyTest and the similar examples above, because collapsing the lambda expression means hiding the *behaviour* the user intends to view.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Recently, I was writing a test method similar to this: \/** * SOME_FEATURE is a constant that identifies a feature the application provides if enabled *\/ void transferMoneyTest() { withEnabledFeature(SOME_FEATURE, () -> { \/\/ line one of the test method [&hellip;]<\/p>\n<div class=\"link-more\"><a href=\"https:\/\/adrhc.go.ro\/blog\/lambda-expressions-with-many-lines\/#more-5153\" class=\"more-link\">Continue reading &#10142; <span class=\"screen-reader-text\">Lambda expressions with many lines<\/span><\/a><\/div>","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[36,10],"tags":[],"class_list":["post-5153","post","type-post","status-publish","format-standard","hentry","category-java","category-programming"],"_links":{"self":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/posts\/5153","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/comments?post=5153"}],"version-history":[{"count":45,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/posts\/5153\/revisions"}],"predecessor-version":[{"id":5246,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/posts\/5153\/revisions\/5246"}],"wp:attachment":[{"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/media?parent=5153"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/categories?post=5153"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/adrhc.go.ro\/blog\/wp-json\/wp\/v2\/tags?post=5153"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}