Think when developing

    Recently I came across an error in the Yandex.Metro Android application. If I were the world champion in synchronized swimming, I would definitely ask: “Who created the program for show?” Who worked “to get out of the way”? Who is the weak link? ” What was perplexing was not the error itself, but the fact that it got into the application and is still not fixed.

    In this article I will describe simple tips that will help improve the quality of programs. I can illustrate them using the Yandex.Metro application errors. I hope that this will be useful to both developers and testers, and project managers.

    I would like to start with the chapter “Studying the famous (and not very famous) mistakes” from the book “The Science of Debugging”. If you have not read it, I recommend reading it. This chapter describes “stupid” mistakes and circumstances that cost lives and millions of dollars. All of these errors were united by the fact that the test script revealing them was extremely difficult to reproduce, as a result, many checks were simply skipped.

    In the article, we will consider common applications that can be tested by any member of the team. Let's do a little experiment. If you don’t have an Android device, ask your colleagues or friends for ten minutes. Download the Yandex.Metro appand try to test it. Interested in the current version 1.63 of 11/02/2012 build 159 (on Google Play is the date 01/21/2013). For verification, I suggest unchecking "Auto-update" in the settings of Google Play.

    We will check the main function: finding the route between two Moscow metro stations. Look at the metro map . Think about what you should test in an application, which might be improperly implemented. A clear error will be the message “Routes not found”, which is incorrect, since there are no isolated stations.

    The same error may not manifest itself so explicitly:
    little hint
    The program displays the routes between two stations, but does not find the most obvious (and short).

    I am sure that many of you have found a mistake. Let's try to figure out where it came from. Simplify the development process to three roles: task manager, developer and tester. At what stage did they add the error? It is difficult for me to imagine a director who will say that if no routes are found, then an appropriate message should be issued. The tester, most likely, could only ask to replace one message with another, but not add logic. The developer remains.

    The message states that no routes were found, which means that the algorithm failed. This is where the first signal should have been for the developer. You can’t just brush aside the impossible code. You must either try to check it, or set up feedback. But, I assume that this error was regular during the checks, when the map of the metro lines was incoherent.

    1. Invariants

    There is such a concept as an invariant of a cycle . Using it, you can prove the correctness of the cycles. Many errors are detected immediately.

    Instead of checking the invariants, some programmers are trying to “unwind” the cycle in the head: “we have a distance of ten, here we will reduce by two stations, but we will add a transfer, as a result we will become closer to one station ...”. The main mistake is that with this approach, a specific path is checked, and invariants are not formulated.

    To understand what this concept is, look, for example, a book written by A. Shen. Programming: theorems and problems (link taken from here ). Although this is a manual for studying at school, both simple and rather complex tasks are explained and solved in a simple language.

    2. Algorithm verification

    Suppose the algorithm is written. For simplicity, we assume that it is implemented as a function. During the implementation, there were dead-end branches that they should never have reached. How to check the algorithm?

    Firstly, you should try to run the function with at least some correct parameters. Among the correct parameters, choose boundary and kinks.

    Secondly, you can try to “spin up” exceptional situations in order to understand at what parameters the chances of an exception appearing increase.

    Thirdly, evaluate the set of initial parameters. It is possible that it will be possible to conduct full testing within a block. If we return to the problem with the metro, then it is enough to check only 188 * 188 = 35344 options. This can be done very quickly. After checking, the algorithm may still not find the optimal routes, but it certainly will not fall into the exceptions.

    3. Exceptions

    Sometimes developers need to handle errors, and errors are not regular, that is, they should not have happened at all. I will give an example from life. Once, the CD crashed in the drive. The system could not understand what was happening, because there was a disk, then the drive did not open, and now there is no disk. As a result, an error was issued: "An unexpected error occurred." There is no value from such a message to either the user or the developer. There is no clue for the user what to do next, but it is not clear to the developer what the reason was. If you throw an impossible exception to the user, then try to add at least some information that will help to understand the situation.

    Using the exception engine built into the programming language is very convenient. Just one line is enough to report an error, and there is no need to check the result of the function each time. If the function can throw an error, then just throw an exception. Often you can see ignoring exceptions. An exception arose, he was caught and continued to work. Then an error will occur somewhere, but no one will know its causes. For example, instead of the message “file not found”, the error “invalid configuration file” will be displayed. You should catch only those exceptions that you handle yourself or distribute above.

    4. Feedback

    No one is safe from mistakes; therefore, it is necessary to foresee what to do if an error still arises. The easiest way is to transfer basic information about the input parameters to the program website. Before that, you can ask the user to make a similar transfer. If you look at the permissions of the Yandex.Metro program, then one of them is “Unlimited access to the Internet”. Why not report a pair of problematic stations with an error?

    Suppose you have an honest offline application, in this case you can offer the user to send an email (including automatically) or just open the page in a browser. Even if it is not possible to pass all the necessary parameters through the address bar, then encode errors in the form of numbers. You will at least have statistics on the occurrence of errors and their place in the program.

    You should definitely not send to a site where registration is required. You need to find out about the error, and not the user to report it. As an exception, you can offer compensation (including virtual) for errors found.
    If you propose to fill out an error form, then enable the user to copy the already prepared text with a description of the error. Firstly, it’s much easier for him than inventing and typing, and on the phone it’s not very convenient. Secondly, you can include important information. Otherwise, a message may appear: “How many times I launch it - it does not work!”. Of course, the user always has the opportunity to give a low rating in the app store and leave a review, but this is not the best solution.

    If nothing is done, then you can wait for a detailed review of the error on Habrahabr or mention on one of the WTF sites.

    5. Simple and standard algorithms

    When developing programs, try to create the simplest algorithms to minimize the number of possible errors. It will be possible to optimize later, but a fast erroneous algorithm is always worse than a correct one, but still slow.

    The second point is the use of standard algorithms. If possible, use ready-made implementations. Categorically you can not use your cryptographic protection algorithms, take standard implementations. A serious vulnerability could be the price of an error, for example, read about WPS .

    6. Testing

    Many developers do not like to test their programs. Often testing is limited to the example proposed in the statement or some simple options. Most often, there are only two reasons. Firstly, the developer himself wrote this code and there should not be errors. In fact, testing will mean an increase in the development period, and the developer is good and can do it faster. Sometimes some constants, temporary settings directly in the code, a fixed language, etc. are forgotten.

    Secondly, it’s important for the developer to feel that the goal has been achieved. He has been trying for a week to make this object move around the screen, compile code, etc. Now something has worked. The hardest part is behind, and the developer has no desire to resume the search for errors. Now he is well done, because the program has started and is doing something. If many errors are reported tomorrow, they will be easily fixed, and this will be another victory. If the developer immediately spends another day searching and fixing errors, then he will not receive a prize for this. The problem is that the tester can also miss the error, and he may need much more time to search.

    The lack of testers is well written by Joel Spolsky .

    7. We begin testing

    What should be checked during testing, what should I pay attention to? First, you need to check the standard cases. For example, for a metro map, take two stations on the same line, but on opposite rays relative to the roundabout, and verify that a direct non-stop route is offered. Then you can take two intersecting lines and check that the one-transfer option is in the results. Next, check that if the lines do not intersect, then the program finds a route with two transfers.

    Then it is advisable to check the boundary options, for example, the program correctly processes the situation when the user tries to find a route between the same station and between stations connected by a transition. To the objection that no one would lay a route between neighboring stations I will answer that the program provides for the entry of stations by name, and the city guest may not be aware of the location of stations on the map.

    Then you should look at the condition and meaning of the task and perform a check at critical points (“kinks”). If you look at the Moscow metro map, then four groups stand out among all the stations:
    1. (Novokuznetskaya, Tretyakovskaya) - for some combinations for transplantation it is enough to just cross the platform;
    2. (China City) - similar to the previous group;
    3. (Okhotny Ryad, Revolution Square, Teatralnaya) - the transition between the Okhotny Ryad and Revolution Square stations is possible only through the Teatralnaya station;
    4. (Alexander Garden, Arbat, Lenin Library, Borovitskaya) - the transition between the Alexander Garden and Borovitskaya stations is possible either through the Arbat station or through the Lenin Library station.

    When checking these nodes, it turns out that if transit is necessary, the program gives an incorrect result. Routes: “Okhotny Ryad” - “Revolution Square” and “Alexander Garden” - “Borovitskaya”.

    During testing, it is recommended that additional checks be performed, as a result of which all provided messages of the program should be received.

    8. Error found

    When an error is found, you should definitely check all related options. It is possible that the error is typical in many cases.

    At Yandex.Metro, the program refuses to search for a route between the Arbatskaya (blue) and Borovitskaya stations, and the route between the Smolenskaya (blue) and Borovitskaya stations is laid through the Kievskaya station. If you expand the search area, you will find that the program correctly paves the route between the Smolenskaya (blue) and Chekhov stations.

    You can also look at the found route options between Mayakovskaya and Maryino stations, as well as between Tverskaya and Maryino stations. You can see some discrepancy, which shows the different processing of the stations in the algorithm when they are at the transfer nodes. You can make sure that the fastest route (according to the program) is not always the first on the list.

    "He won't stand beating"

    He decided to make a quote from Alice in Wonderland in the title. In the cartoon, Alice’s phrase about the killing of time was answered that “he does not like this.”

    If the program uses time, then you need to carefully develop the program and test it. Recently, an error was submitted on 02.29.2013 on the Russian Railways website .

    When we talk about time, we must remember that there are different time zones. If you ever scheduled conferences with someone from other countries, then without an explicit time zone, problems could arise. If the client software is not configured correctly, then when creating a meeting, errors may also occur, for example, I receive a notification about the meeting, and the error due to summer time can be in an hour. If you write any date and time in a letter, be sure to write the exact time zone. In programs, be sure to keep the time zone near the time, or store everything in the same time zone.

    Just a couple of days ago I came across an error in the Wolfram Alpha search engine. She gives the right answer to a certain range of questions. Examples of such queries and areas of knowledge can be found, for example, on The

    error in the search engine is extremely simple: it still does not know that the Moscow time zone (MSK) has changed and corresponds to UTC + 4. As a result, all requests for time for Russia are incorrect. I wrote about the error to them, I will inform you about the answer.

    What caused this error? Most likely, the program simply uses some table with time zones, and no one thought about updating it. Maybe they thought, but they did not waste time processing such a situation. It is possible that the problem is in winter time.

    When it comes to time, any tester should check for leap years, as well as switching to summer and winter time. At the same time, I draw attention to the fact that in the spring there will simply not be one hour (at two in the morning there will be three hours of summer time at once), and in the fall the interval between two and three hours of nomi will be covered twice (once in summer time and once in winter time) ) We ask Wolfram Alpha a question about the difference between two points in time . The system correctly subtracted one hour. Do you take this into account in programs?

    We also need to look at the behavior of the program at the border of midnight, when time comparisons no longer work (23:59 and 00:01), and the dates began to differ. What happens if you start a certain operation in the program today and continue tomorrow? When developing a program that works over time, you should be very careful.

    When week numbers are used, they must also be checked. The fact is that if the first of January falls on Monday, Tuesday or Wednesday, then the next week will be considered the first. A few years ago I met the erroneous definition of weeks in Nokia phones. Such a mistake is sometimes made by designers when designing calendars.

    Another problem is associated with time - personalization of the time zone. Imagine that I am in a different zone relative to the server, in this case, obviously, I want to see the time in my time zone. If I travel often, then in every trip I have to compare the time not only with the server, but also with the one saved in the settings. Often in the settings of forums and sites it is suggested to select the time zone and the choice starts from GMT-12. And nowhere is there a simple option "my current time zone." If I change the clock in the operating system, it would be nice to see the time in the corresponding time zone. The only problem here is the inability to immediately determine which time zone we are talking about.

    Think about users

    If you write the program only “for show,” just to be, then you can no longer read on. When you create a program, you should understand for whom exactly you are doing it, what tasks it should solve, etc. The task is not just to release a product, but to create a product for specific categories of users. Try to ask a question what else this particular user might miss.

    Back to Yandex.Metro. The program added a notification that the metro is closed at a certain time interval. It works when you start the program or change the card. But only once per session. The main minus is that if the program has already been launched earlier, then when plotting the route, the user will not be able to find out if the metro is closed. This is one of the comments. On the other hand, the program is often used not only after entering the subway, but also in advance to plan a trip. Why not add a subway closure warning in a couple of hours? Additionally, you can add a help page where you can specify, for example, hours of operation and fare.

    As for the operating time of the metro, even such a simple function was implemented with an error. Suppose someone came from Moscow to Kiev or Minsk. Opens the program and receives a message that the metro is closed. But still a lot of time before closing. The fact is that it is midnight in Moscow, and the program does not even think to check the time zone, but only focuses on the current time:

    What else in the metro depends on the current time (except for opening and closing)? Firstly, it is the intervals between trains and waiting times. We will talk about this a bit later. Secondly, these are the possible overlap of stations or crossings due to the repair of escalators. Considering that information on escalator repair and changing station operating modes is rarely updated, it would be very nice if it was displayed on a map and taken into account when plotting a route. Additionally, it can be simply described on the tab "News".

    I will dwell separately on the waiting time for trains. If you look at the description of the online version of Yandex.Metro , then it says:
    3. What time is considered and why is it approximate?
    The travel time between stations, the transition time from line to line is considered. The time of descent or ascent along the escalator at the start and end stations is not taken into account. The average time is taken for the crossings and thoroughfares, and for various reasons it may differ by a couple of minutes from the real time (for example, the train arrived at the wrong time or a lot of passengers accumulated at the crossing).

    7. Where do the data for calculating routes come from?
    To calculate the routes, the data of the MMetro program Konstantin Shtennikov is used.

    If someone has not seen the MMetro program, then in it, when selecting a route, you can set the accounting mode for the waiting time: do not take into account, daytime, evening or early morning. You can check that in the seventh question it is correctly written that the online version of Yandex.Metro takes MMetro data as the transition time and travel time between the two stations. Train wait times are not taken into account at all. That is, "the train arrived at the wrong time" from the third paragraph means that "you have arrived, but there is no train." Long waiting times in the evenings require routing with a minimum of transfers. With this in mind, there is an obvious cunning in the second answer: “The route we are proposing will appear on the diagram, and the panel to the right of the diagram will describe in detail how to go and how long the trip will take.”
    The Android version of Yandex.Metro uses the same data. I’ll quote Ami Meio from January 2, 2013: “New metro stations are open already on the 5th day, but they are still not on the map (and the program always lies about the trip.” The description on Google Play reads:
    Finding the best route in the metro. The application does not require an Internet connection - so you can use it directly during the trip. Plan underground routes in Moscow, St. Petersburg, Kiev, Kharkov and Minsk. Find out your trip time with transfers. And the Metro will tell you which part of the train it is better to board in order to get there faster.

    The Yandex.Metro mobile application has:
    - automatic construction of the optimal route;
    - calculation of travel time;
    - replenishment of the ticket “Podorozhnik” (St. Petersburg);
    - And also, if your phone supports NFC (Galaxy Nexus, Google Nexus S, Sony Xperia S and HTC One X models), then using the application you can find out how many trips are left on a one-time Moscow metro card.

    We have already looked at the declared correctness of the calculation of the travel time. These, of course, are trifles, but the application is not only an apk file, but also a description on the site. My eyes caught on the following: (a) the absence of a space after the first sentence; (b) in the second sentence, the word Internet is written in lowercase; (c) in the second sentence, it is not clear what you can use during the trip: the application or the Internet; (d) at first the words are written without using the letter “ё” (“accounting”, “yet”), and then the letter “ё” appears in the word “calculation”; (e) the last sentence reads “Moscow Metro”.

    It is not entirely clear how the phrase “the application does not require an internet connection” relates to the required permissions:
    Unlimited access to the Internet. The
    application will be able to create network sockets and use various network protocols. Since the browser and other applications independently implement the functions of sending data to the Internet, this permission is not required.
    Connect / disconnect Wi-Fi network The
    application can connect to and disconnect from Wi-Fi access points, as well as change the configuration of Wi-Fi networks on the device.
    Change network settings
    Allows an application to change the status of a network connection.

    Most often, I launch Yandex.Metro to find out which part of the train you should board in order to get closer to the desired passage or exit. This is a very good idea. Unfortunately, there are comments on the implementation. Firstly, it is rather difficult to determine a specific car number based on the image. I can assume that five cars mean: the first car, the beginning of the train, the center, the end of the train and the last car. Perhaps it would be a little more obvious to add an arrow in the direction of the transition, that is, the direction of movement after leaving the car. But the main problem with exits from wagons is that at many stations there are fences, because of which the exit from the first wagon turns into bypassing the fence through the center of the hall. I tried to get there faster, but then, on the contrary, I am wasting my time. Why not adjust the settings?

    When traveling to a specific address, one of the problems is determining the desired exit. If there is only one way out, then Yandex.Metro will help. If there are several outputs, then the 2GIS program will help. She knows how to make a route taking into account trips by subway. But the final touch was blurry. Take a look at the screenshot. We need to get to the Tulskaya metro station, but they lead us to the center of the station, and not to one of the entrances to the station (indicated by the letters "M" in the upper left and lower left). With exits from the subway the situation is similar. Be carefull!

    One of the recent trends is the creation of programs without a description. You get something and don't know what it does. It is believed that the interface should be clear. Why not give more information about the program objects?

    The only “informational” document available in the program is a license agreement . I have a question about points 5.1 and 5.2:
    5.1. The User is hereby notified and agrees that when using the "Locate" function in the Program, the Program receives data on the coordinates of the User’s location and transfers it to the Copyright Holder to display the metro station closest to the User until the specified function is turned off.

    5.2. The user can at any time refuse to transfer the data specified in clause 5.1 by disabling the corresponding function.

    The standard Android function "location" is turned off and the Maps application refuses to determine my location. There is no additional option in Yandex.Metro settings.

    But Yandex.Metro continues to find the nearest metro station. That is, there is a violation of the license agreement by Yandex (or just a lie)? The situation is similar with the agreement on the Yandex.Maps program , where location is mentioned only in clause 5.3:
    5.3. The User is hereby notified and agrees that when the “Report traffic jams” function included in the Program is activated, the Program transfers to the Rightholder anonymous data on the exact location and parameters of the User’s movement received from the GPS device, or on the approximate location of the User, determined by the active cell of the service provider , the SIM card of which is currently being used in the User’s mobile device, to collect statistical information about the state of the road, until the moment of disconnection Nia said function.

    But even with the "Report traffic jams" function turned off, the program continues to show the current location (the standard Android function is still turned off).

    Hiding behind AS-IS, companies can irresponsibly release software products of any quality. Sloppiness is not punished while “people hawl”, you can do everything “to get out of your way”.


    Enough “turn on the brain” in the development and testing to improve the software product. Try to think as a user, put yourself in his place. If it doesn’t work, then find a typical user and talk to him. Not only the task manager, but the whole team should feel the desires of the client. A high-quality product gives joy not only to the user, but also to you. I hope this article is useful.

    Addition. An answer came from Wolfram | Alpha with gratitude and information that the comment was sent to the developers.
    I will answer the main comments.
    Firstly, I have no hatred for Yandex or its developers. The purpose of the article is to help avoid mistakes. The Yandex.Metro application was used only as a good illustration. The academic approach is interesting, but I think that an ordinary article with tips would get comments: “everyone knows that already”, “no one makes such mistakes”, etc.

    Secondly, everyone makes mistakes, including me. Specially began the article with a proposal to read the chapter “Studying famous (and not very famous) mistakes” about “stupid” mistakes that cost a lot. The main question in relation to their work and the desire to make a quality product. It’s not so difficult to get better.

    Also popular now: