{"id":7616,"date":"2018-06-13T15:30:17","date_gmt":"2018-06-13T18:30:17","guid":{"rendered":"http:\/\/blog.plataformatec.com.br\/?p=7616"},"modified":"2018-06-13T15:54:58","modified_gmt":"2018-06-13T18:54:58","slug":"the-anatomy-of-code-documentation","status":"publish","type":"post","link":"http:\/\/blog.plataformatec.com.br\/2018\/06\/the-anatomy-of-code-documentation\/","title":{"rendered":"The anatomy of code documentation"},"content":{"rendered":"

Writing code is the activity that turns our ideas into great products and tools.<\/span><\/p>\n

Fingers over a keyboard and a text editor. This is how most people see our daily routine. Suddenly, no words emerge over the screen. The eyes gaze at the monitor and everything looks static: we\u2019re reading code.<\/span><\/p>\n

(And we read lots<\/strong> of code).<\/span><\/p>\n

The reading process demands a huge cognitive effort from us. Once we read a piece of code for the very first time, we\u2019re immersed in a long learning curve and a continuous cycle of questionings, doubts, and insights. Reading code requires us to dig through the mental model of a domain problem and to continuously analyze the input, processing and output flows of some business requirement.<\/span><\/p>\n

Sure, good developers have been exposed to good writing practices, and there is nothing like reading a clean, robust and elegant piece of code. Our methods are small and expressive and intend to reveal interfaces. <\/span><\/p>\n

Nevert<\/span>heless, we still must read them line by line, and gradually lay down our understanding about it.<\/p>\n

(“Only well written and tested code is not enough to connect the dots\u2026”, some wise person may have already said this before.)<\/em><\/p>\n

A large number of whiteboard discussions may have been lost, merely because there was no room for those. Commit messages were laconic and our memorization skills were overestimated. Yesterday\u2019s obvious is now a mine of untangled knowledge.<\/p>\n

Furthermore, the practice of comment about code is often discouraged. After all, we prioritize working software over overwhelming documentation. We\u2019re agile developers and we cannot afford the maintenance burden. Code comments are mostly faced as the inability to express oneself in a clever way, and the activity of documenting code is usually associated with redundant, undesired and ungrateful comments.<\/p>\n

But here it goes: the key point on documenting is maintaining information that resists as time goes by.<\/strong><\/p>\n

A practical example<\/h2>\n

Suppose our sample application deals with a concept of contracted plans on its domain, where each plan offers a storage limit in a remote storage service. One of the requirements is to present a summary of a contracted plan\u2019s consumption, as shown in the example below:<\/p>\n

'2.44% (500 MB of 20 GB)' # User has consumed 2.44% from a 20 gigabytes\n                          # storage limit (i.e., 500 megabytes).\n<\/code><\/pre>\n

Our source data is a domain object ContractedPlan<\/code>, which exposes two main pieces of information: the storage limit value (in the plan_storage_limit column<\/code>) and the total consumed (in the total_consumed<\/code> column) until the present moment, both persisted in numeric bytes in the database.<\/p>\n

The consumption summary must present these two pieces of information, in addition to the percentage of how much has been consumed until now:<\/p>\n

\\> contracted_plan = ContractedPlan.last\n\n\\> contracted_plan.plan_storage_limit # Client has contracted a 20 GB plan.\n# => 20_000_000_000\n\n\\> contracted_plan.total_consumed # User has consumed 500 megabytes until now.\n# => 500_000_000\n<\/code><\/pre>\n

The percentage of how much has been consumed can be calculated simply applying the following statement:<\/p>\n

\\> total_consumed_in_percent =\n  (total_consumed * 100.to_f \/ total_contracted).round(2)\n# => 2.44\n<\/code><\/pre>\n

Knowing that such summary statement must be rendered in an HTML page, we\u2019re gonna create a ContractedPlansHelper#plan_consumption_summary<\/code> helper with the following implementation:<\/p>\n

module ContractedPlansHelper\n  def plan_consumption_summary(contracted_plan)\n    total_contracted = contracted_plan.plan_storage_limit\n    total_consumed = contracted_plan.total_consumed\n    total_consumed_in_percent =\n      (total_consumed * 100.to_f \/ total_contracted).round(2)\n\n    format(\n      '%s%% (%s de %s)',\n      total_consumed_in_percent,\n      number_to_human_size(total_consumed, precision: 4),\n      number_to_human_size(total_contracted)\n    )\n  end\nend\n<\/code><\/pre>\n

The #plan_consumption_summary<\/code> method has a structure divided into two main parts: data preparation and data presentation (including the step for formatting the three expected pieces of information).
\nEven though it looks like a simple and straight logic, there are some points not so obvious for newcomers to that code. The data presentation part depends on a moderately complex structure, in a way that is not an easy piece to digest regarding the “shape” of the returned String (i.e., the syntax of the format method, besides the two calls for the #number_to_human_size method<\/code>).<\/p>\n

There are, of course, some ways to find out how the returned text will be printed out:<\/p>\n