A successful software product usually goes through the hands of many developers in its lifetime. You are just one of the links in the chain of trustees of your project, and each line of code you wrote is an artifact you left behind that will someday be studied by the Future Developer. Also, as you inherited the decisions of the developers that were before you, other developers will inherit the decisions that you made today. They inherit from us all our misunderstandings, the corners we cut off, the misunderstood patterns and techniques we used, our inattention to details, our laziness, our changes made in haste, our skeletons in the closets, our dirty laundry. And much less often - the benefits of our discipline, our discussions and preparations.

As a developer of your project, you are in the best possible position to anticipate and take care of the needs of the Future Developer. Every good decision we make in our project will have a ripple effect for its productivity. Why is it important? As Bob Martin asks in the
Clean Code book: “Have you ever experienced problems due to bad code? Then why are you writing it? ” The same strategies that will improve the conditions for the generations of teams that will work on your project in the future will serve as good to your team in the present. When you return to the dark corners of the code that you put on six months ago, you know a little more about it than the Future Developer will know when he sees it for the first time. From the prompts and gloss that you leave to other developers, in the future you will also win. Projects that are in poor condition and are difficult to contribute to lead to team exhaustion. Investing in quality and ease of future support for the product you create is an investment in a happy, productive workplace for the future and the present.
I want to make out a few practices (without any specific order) that we can use to direct the Future Developer straight to success.
')
1. Holistic refactoring
As the project matures and the requirements become more complex, we strive to apply new patterns and techniques to control this complexity. It is impossible to immediately say whether the pattern or the approach will cope with the task entrusted to it. Most of the time, confirming or denying its significance comes when another developer has to make changes to this part of the code. Sometimes these patterns grow into agreements that we accept to solve problems.
There is a huge benefit from this: it explains our intentions. If we try to solve problems in code in a similar way, the Future Developer can begin to predict how pieces of code work together, thereby reducing the amount of time needed to diagnose and make changes.
Often what we reserve for ourselves is a jumble of patterns that never turned into conventions or were ignored in the code as old junk. This happens for various reasons: the agreements adopted do not work so well as to apply them in other areas of the project, or maybe new developers were not aware of the existence of a suitable agreement or pattern to achieve the goal.
Inside Ruby on Rails, many powerful views and conventions have been established. They allow developers to connect to the project and immediately become productive, provided that they have had experience with this framework before. Sometimes we treat these agreements scornfully, thereby weakening their strength. For example, in rail projects, periodically you can see controllers built in several different styles. Some are compiled using something like
resource_controller
, others follow the standard Rails resource agreement, while still others are just garbage dumps from random actions. Another common anti-pattern is configuration data scattered throughout the project and initialized wherever possible.
There is no need to support half a dozen different ways of setting up your system, make it clear and understandable on what principles the controller should be built within the project. Experimenting with one approach and taking it, take the time to go back to the old code and refactor it in a new way. This does not mean that you should impose any arbitrary restrictions. It makes sense to, for example, keep a part of the config inside the project, and a part in the environment variables to help with the deployment, but there should be one common structure and pattern of access to the use of configuration data.
Add conventions to your README or documentation repository. At first, this will simplify the future developer to add new functionality to the system and give an understanding of how its components are built.
2. Eliminate the Dead Code
Another common feature of systems that have already survived for some time is a layer of moss in the form of a dead code. These are components of your project that could have been important for business some time ago, but they were outdated and for a long time nobody needed them. Most likely in the project you can find a large number of full-stack acceptance tests that test such parts of the functionality, and now these tests only slow down the passage of the rest.
Sometimes we are reluctant to remove such code, because we can not always be sure that this feature will never be demanded again. If you ask the manual, it will answer your question: “Leave, it will ever come in handy.” This is a false dilemma - you need to maintain a slowly rotting piece of code, because sometime in the future, it may be possible to use it again just by clicking your fingers. If we bypass this code side, because of its irrelevance, it is unlikely that it will just be so easy to click your fingers and get it to work without much difficulty. You care that the old code pulls you up to the bottom, makes you spend time supporting it, just because there is a scant chance that it will be needed once. May be. You do not notice, but you spend a lot of time on it, and instead of removing such code, you allow it to slowly rot in the repository.
But what is even more costly is that the existence of this code is a potential trap for the Future Developer. This distracts attention from those components of the system that are actually alive, and can lead to a false mark when he tries to understand or debug some aspect of the system. In emergency situations, when everything has fallen, the dead code is the noise that is waiting for the moment to take up valuable time. By keeping in your repository only up-to-date, lively and in fact functioning code, you will reduce the total cost of supporting the project and allow the Future Developer to understand the entire system much faster.
Delete the code that has long been abandoned. In the end, it is still under version control, in case you need to return to it later. Do not be fooled by the need to "come back to him again later." If this code had any meaning, then why is it not already used?
3. Keep the information
Besides, actually, our project, some tools that we use for writing code also have their own artifacts. For example, there are many accepted practices about what constitutes the hygiene of a good message when git commit, and at the same time projects still continue to collect such commit stories:
jp@oeuf:~/workspace/blog(master*)$ git log --oneline app/controllers/application_controller.rb 8ec7f99 fuck i dunno lol ffa919a shut up, atom parser a33e9fa fixing again cecc9dc one more time 968a28f fixing 3e3aeb2 ws 1fc597e pagination edea155 adding dumb feature
In the event that the Future Developer will inevitably come to the use of git blame to understand the context of this feature, leave him details that will help to understand what is happening in the files in fact. Use
--squash
,
commit --amend
,
rebase
and other tools to bring commits to a suitable state before integrating your branch. Rephrase your commits when done - take a minute to include everything that seems appropriate and summarizes the work done. Correct grammar and spelling; You publish something that will have to be read and understood by another person. Provide the Future Developer with a service and make sure that you reserve a clear record containing as many details as you need:
jp@oeuf:~/workspace/blog(master*)$ git log app/controllers/application_controller.rb commit 8ec7f998fb74a80886ece47f0a51bd03b0460c7a Author: John Pignata <john@pignata.com> Date: Sat Nov 3 14:11:12 2012 -0400 Add Google Analytics helper commit 968a28f366e959081307e65253118a65301466f2 Author: John Pignata <john@pignata.com> Date: Sat Nov 3 13:49:50 2012 -0400 Correct ATOM feed validation issues Using the W3C Validator (http://validator.w3.org/appc/), a few trivial errors were reported: * <author> should have a <name> node within it and not text * Timestamps should be in ISO8601 format This change fixes these issues and improves the spec coverage for the XML document. commit 3e3aeb27ea99ecd612c436814c5a2b0dab69c2c3 Author: John Pignata <john@pignata.com> Date: Sat Nov 3 13:46:24 2012 -0400 Fixing whitespace We're no longer indenting methods after `private` or `protected` directives as a matter of style. This commit fixes whitespace in all remaining classes. commit 1fc597e788442e8cc774c6d11e7ac5e77b6c6e14 Author: John Pignata <john@pignata.com> Date: Sat Nov 3 12:34:50 2012 -0400 Implement Kaminari pagination Move from will_paginate to kaminari in all controllers. The motivation is to be able to paginate simple Array collections without the monkey patching that will_paginate uses. * Consolidate helpers * Clean up whitespace commit edea15560595bab044143149a7d6e528e8ae65d2 Author: John Pignata <john@pignata.com> Date: Sat Nov 3 12:27:16 2012 -0400 Add ATOM feed for RSS readers * Include Nokogiri in Gemfile for its builder * Add AtomFieldBuilder model * Add link to feed from index page
4. Place your gloss on your interfaces.
Some Rubists avoid visible methods in their objects. What is the purpose? Any method is actually called via send, whatever one may say. Why to shackle some of them? Just add a heap to the rest, and if the Future Developer wants to use it, he can! We are all adults, aren't we?
If every object in your system is just a dump of methods, then it becomes difficult for everyone (including you) to understand how each individual object was supposed to be used and which messages it was intended for. The design of the public interface of an object should make absolutely clear how other objects in the system can interact with it. When the role of each object and the interactions between them in your system are not obvious, the time it takes to understand not only each of them separately, but also the system as a whole, grows.
Hide as much as possible the insides of the components to keep the interface small and focused. Make extra efforts to make sure that the public interfaces of your object are clear, consistent and have good names. This will give the Future Developer clear signals about how you planned to use each of the objects and emphasize how each of them can be reused. Explicitly indicate the visibility of methods to convey these prerequisites and to maintain clear boundaries of the public interface.
5. Leave comments, not too much, mostly RDoc
Our feelings, as developers, to comments in the code can most accurately be described as contradictory. On the one hand, comments are very helpful to the reader in understanding how a certain piece of code works. On the other hand, nothing guarantees their correctness; comments on the code are lies that are waiting in the wings. If you ask the developers, they will answer that they appreciate and read the documentation, but most of the projects actually have a small, almost-out-of-date README file and a wiki grave somewhere nearby. Moreover, working with open source libraries, we often expect detailed RDoc documentation, a fresh README file and good code samples, and when we don’t find any of this, we swear dirty. Bloody developer: does not support the documentation, probably waiting for someone to do it for him.
The more we pay attention to things like the Single Responsibility Principle and use the patterns of weak connectivity between objects, we begin to see systems made up of many small objects combined together during the program. Although this makes systems more flexible, and it becomes easier to use objects many times, there is a trade-off: understanding the place of an object inside a large system becomes more difficult, it takes more time and effort. You can apply all the usual refactoring techniques to remove annoying line comments and make the object as readable as possible, but how the object should interact in the system can still confuse the Future Developer.
RDoc-style documentation can be found in many open source projects. When you use Google to understand whether callbacks are using
update_attribute
or not, and which
select_tag
has a signature, you usually go to the RDoc page for Ruby On Rails. Writing similar documentation for your project will give the Future Developer more insight when he tries to define the role of an object in the vast context of your system. Having a short, declarative sentence at the top of a class and / or method that indicates what it is responsible for can be essential for the reader of the code. But without a well-established culture of supporting the relevance of these comments, they can also have a negative impact, disorienting the reader of the code. Remember, the only thing that can be worse than the lack of documentation is bad documentation.
6. Write tests that reveal your intentions.
One of the ways to provide project documentation is tests. Tests not only describe the behavior of components, but also ensure that such documentation is of high quality, since she is being executed. Unlike comments, we can not lie in the tests. They are either green or not. Tools such as RSpec and minitest / spec help us generate this side documentation by encouraging prose inside the test case block. Unfortunately, sometimes we look past the English words, trying to get a working code during the red-green-refactor cycle. As a result of neglecting the English-language description, sometimes it turns out that tests do not reflect the behavior of our objects as well as we think.
Almost as painful as finding a project without tests in general, finding a project whose tests do not help to understand how the system works. Tests are code that also requires support, and therefore they must very clearly explain their purpose to the future of their reader.
it "works" do data = File.open("fixtures/projects.txt").read index = ProjectIndex.new(data) index.should have(40).projects last_project = projects.last last_project.title.should eq("ORCA") last_project.customer.should eq("Romney-Ryan 2012") last_project.deploy_date.should eq(Date.parse("2012-11-06")) end
Well, what does "work" here? This description in one word is meaningless, and in the example several tests take place at once, which leaves no sense at all.
If you write tests in the style of specifications, English descriptions should follow you. One way to achieve this is to run RSpec in a documentation format:
jp@oeuf:~/workspace/project-manager(master)$ be rspec --format documentation spec ProjectIndex .new instantiates an index given the contents of a project CSV file
Instead of a forest of green dots, the format of the documentation gives out nested descriptions, contexts, and headings of the examples you specified. This allows you to quickly assess how completely the tests reveal the actual behavior of the object. By focusing on the issue in this format, you can significantly improve the communicative value of the test suite. Use the refactor step in the red-green-refactor cycle to turn your tests into a clear explanation of the reason for the existence of the object, how it behaves, and why it does so.
The future developer is delighted
These are just a few ways we can prepare a project for change, with a reasonable assumption that someone else will pay the bills. Think of the next pair of eyes that will be responsible for building and operating your current project while you are still working on it. We all have ever experienced remorse because of the complexity of support or the poor quality of what was produced. So stop feeding warm feelings to all those pretty rakes you left in the code, and instead start slowly counting the amount of drinks that the Future Developer will owe you for how well you prepared the ground for his arrival.
Thanks to Dave Yeu from whom I borrowed (read: stole) the term “future developer”.
Any thoughts, questions or comments? Share them, please! I can be found on Twitter under the nickname @jpignata, and I am also available by email john@pignata.com. Thank you for reading!
Let me remind you that this is a translation, and the coordinates above refer to the author of the original article. I will be very grateful if you send me your comments and comments in PM. Thank.