
Recently I stumbled upon an error in the Android application Yandex. Metro. If I were the world champion in synchronized swimming, I would definitely ask: “Who created the program for a tick?” Who worked "off your mind"? Who is the weak link? The mistake was not caused by the error itself, but by 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 Yandex.Metro application errors. I hope that this will be useful both to developers and testers, and to project managers.
I would like to start with the chapter
"Learning famous (and not very famous) errors" from the book "Science debugging .
" If you have not read, I recommend reading. This chapter describes the “stupid” mistakes and coincidences that cost lives and millions of dollars. All these errors were united by the fact that the test script that detected them was extremely difficult to reproduce, and as a result, many checks were simply omitted.
')
In the article, we will consider common applications that can be tested by any team member. Let's do a little experiment. If you do not have an Android device, then ask your colleagues or friends for ten minutes. Download the
Yandex.Metro application and try to test it. Interested in current version 1.63 of 02.11.2012 build 159 (on Google Play is the date 01/21/2013). For correctness of the check, I suggest removing the “Auto Update” checkbox in the Google Play settings.
We will check the main function: finding the route between the two stations of the Moscow metro. Look at
the subway map . Think about what should be tested in the application, which could be incorrectly implemented. An obvious error would be the message "Routes not found", which is incorrect, since there are no isolated stations.
This same error may not manifest itself so clearly:
a little hintThe program displays routes between two stations, but does not find the most obvious (and short) one.
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 director, developer and tester. At what stage did you add the error? It's hard for me to imagine a director who says that if the routes are not found, then I need to issue a corresponding message. The tester, most likely, could only ask to replace one message with another, but not add logic. Remains a developer.
The message states that no routes were found, which means that the algorithm failed. Here for the developer should have been the first signal. You can not just dismiss the impossible code. You must either try to check it, or set up feedback. But, I admit that this error was regular during inspections, when the map of the metro lines was incoherent.
1. Invariants
There is such a notion
of a cycle invariant . With it, you can prove the correctness of cycles. Many errors are detected immediately.
Instead of checking invariants, some programmers are trying to "unwind" the cycle in their head: "we have a distance of ten, reduce it to two stations here, but add a transplant, as a result, we will be closer to one station ...". The main mistake is that with this approach a specific path is tested, and not invariants are formulated.
To understand what this concept is, look, for example, at a book written by
A. Shen. Programming: theorems and problems (link taken
from here ). It may be a school book, but both simple and quite complex tasks are explained and solved in a simple language.
2. Algorithm check
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 should never have been hit. How to check the algorithm?
First, we must try to start the function with at least some valid parameters. Among the correct parameters to choose the boundary and kinks.
Secondly, you can try to “spin up” exceptional situations in order to understand at what parameters the chances of exceptions increase are increased.
Thirdly, evaluate the set of initial parameters. It is possible that it will be possible to conduct a full test within a block. If you go back to the task with the metro, then it’s enough to check only 188 * 188 = 35344 options. This can be done very quickly. After verification, the algorithm still may not find the best routes, but it will not fall into the exceptions for sure.
3. Exceptions
Sometimes developers need to handle errors, and errors are not regular, that is, they should not be there at all. I will give an example from life. One time the CD has crashed in the drive. The system could not understand what was going on, because the disk was there, then the drive did not open, but now there is no disk. As a result, an error was issued: "An unexpected error occurred." Values ​​from such a message there is neither the user nor the developer. For the user, there is no clue what to do next, but the developer is not clear what was the reason. If you give an impossible exception to the user, then try to add at least some information that will help to understand the situation.
Using the exception mechanism 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 may produce an error, then simply generate an exception. You can often find ignoring exceptions. There was an exception, he was caught and continued to work. Then somewhere there will be an error, but no one will know about its causes. For example, instead of the message “file not found” an error “incorrect configuration file” will be displayed. It is necessary to catch only those exceptions that you will handle yourself or distribute above.
4. Feedback
No one is immune from mistakes, so you need to foresee what to do if an error does occur. The easiest way is to transfer basic information about the input parameters to the program site. You can ask the user to make such a transfer. If you look at the permissions of the Yandex.Metro program, then one of them is “Unlimited Internet access.” Why not report a pair of problem stations in case of an error?
Suppose you have an honest offline application, in this case you can suggest the user to send an email (including automatically) or simply open the page in the browser. Even if it is not possible to transfer all the necessary parameters via the address bar, encode errors in the form of numbers. At least you will have statistics on the occurrence of errors and their place in the program.
Do not send to the site where registration is required. You need to know about the error, 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 allow the user to copy the already prepared text with a description of the error. Firstly, it is much easier for him than to invent and type text, but on the phone it is not very convenient. Secondly, you can include important information. Otherwise, you may receive the message: “How many times I start - it does not work!”. Of course, the user always has the opportunity to put a low rating in the app store and leave a review, but this is not the best way.
If nothing is done, then you can wait for a detailed review of the error on Habrahabr or a 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 the fast erroneous algorithm is always worse than the correct one, but it is still slow.
The second point is the use of standard algorithms. If possible, use ready-made implementations. Categorically you can not use your own cryptographic algorithms, take the standard implementation. The cost of a mistake can be a serious vulnerability, 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 formulation or some simple options. Most often there are only two reasons. First, the developer himself wrote this code and there should not be any errors. In fact, testing will mean an increase in development time, and the developer is good and can do it faster. Sometimes you forget some constants, temporary settings right in the code, fixed language, etc.
Secondly, it is important for the developer to feel that the goal has been achieved. For a week he tries to make this object move across the screen, compile code, etc. Now something is working. The most difficult thing is over, and the developer has no desire to resume the search for errors. Now he is great, because the program has started and is doing something. If tomorrow they report a multitude of errors, they will be easily corrected, and this will be another victory. If the developer immediately spends another day searching for and correcting errors, he will not receive a prize for it. The problem is that the tester may also miss the error, and it may take him much longer to search.
About the lack of testers well written in
Joel Spolsky .
7. Start testing
What should be checked when testing, what to look for? First, you need to check the standard cases. For example, for a subway map, we will take two stations on the same line, but on opposite rays relative to the ring road and check that the route is offered in a straight line without transfers. Then you can take two intersecting lines and check that the version with one transplant was in the results. Then 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 handles the situation when the user tries to find a route between the same station and between stations connected by a junction. On the objection that no one would lay a route between neighboring stations I will answer that the program provides for the introduction of stations by name, and the city guest may not be aware of the stations on the map.
Then you should look at the condition and meaning of the problem and perform the check at critical points (“kinks”). If you look at the Moscow metro map, then among all the stations there are four groups:
- (Novokuznetskaya, Tretyakovskaya) - for some combinations for transplantation, it is enough just to cross the platform;
- (China-City) - similar to the previous group;
- (Okhotny Ryad, Revolution Square, Teatralnaya) - the transition between Okhotny Ryad and Ploshchad Revolutsii stations is possible only through the Teatralnaya station;
- (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 necessary, the transit program produces an incorrect result. Routes: “Okhotny Ryad” - “Ploshchad Revolutsii” and “Aleksandrovsky Sad” - “Borovitskaya”.

During testing, it is recommended to perform additional checks, as a result of which all provided program messages should be received.
8. Error found
When an error is found, you should definitely check all adjacent options. It is possible that the error is typical for many cases.
In Yandex.Metro, the program refuses to look 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 Smolenskaya (blue) and Chekhovskaya stations.

You can also look at the found route options between Mayakovskaya and Maryino stations, and also between Tverskaya and Maryino stations. You can see some discrepancy, which shows the different processing stations in the algorithm, when they are on the nodes of transplants. You can make sure that not always the fastest route (according to the program) is the first in the list.
"He won't stand beating"
The headline decided to make a quote from "Alice in Wonderland". In the animated film on Alice’s phrase about the murder of time, they answered that “he does not like this”.
If the program uses time, it is necessary to carefully develop the program and test it. An
error was recently introduced
on February 29, 2013 on the Russian Railways website .
When talking about time, we must remember that there are different time zones. If you have ever appointed conferences with someone from other countries, then without explicit indication of the time zone problems could arise. If the client software is incorrectly configured, then when creating a meeting, errors can also occur, for example, I receive a notification about the meeting, and an error may occur in an hour due to summer time. If you write any date and time in the letter, be sure to write the exact time zone. In programs, be sure to keep your 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. On a certain range of questions she gives the right answer. Examples of such queries and knowledge areas can be found, for example, on
About.comThe 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, 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 didn’t waste time handling such a situation. It is possible that the problem is in winter time.
When it comes to time, then any tester should check leap years, as well as daylight saving time. At the same time, I note that in the spring one hour simply will not be (at two o'clock 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 the room will be covered twice (once in summer time and once in winter time ).
Let Wolfram Alpha ask about the difference between two points in time . The system correctly subtracted one hour. Do you take this into account in programs?
You also have to look at the behavior of the program at the midnight border, when time comparisons no longer work (23:59 and 00:01), and the dates began to differ. What will happen if we start some operation in the program today and continue tomorrow already? When developing a program that works with time, you should be very careful.
When week numbers are used, they should 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, the erroneous definition of weeks was met in Nokia phones. This error is sometimes made by designers when designing calendars.
Over time, another problem is connected - time zone personalization. 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 frequently, then on every trip I have to compare the time not only with the server, but also with the saved in the settings. Often in the settings of forums and websites it is proposed to select the time zone and the selection starts from GMT-12. And nowhere is there a simple option "my current time zone." If I change the clock in the operating system, then 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 is being discussed.
Think about users
If you write the program only for “ticks” so that it is just there, then you can no longer read. When you create a program, you need to understand for whom it is 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 asking a question, what else may be missed by this particular user.
Let's go back to Yandex. Metro. The program added a notice that the metro is closed at a certain time interval. It works when you start the program or change the card. But during the session it works only once. The main disadvantage is that if the program has already been launched earlier, then when laying a 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 warning about the closure of the metro for a couple of hours? Additionally, you can add a help page where you can specify, for example, the time of work and the cost of travel.
As for the time of the subway, 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 subway depends on the current time (except for opening and closing)? First, it is the intervals between trains and the waiting time. We will talk about this a little later. Secondly, it is possible overlap of stations or transitions due to repair of escalators. If we take into account that information about repairing escalators and changing the operating modes of stations is rarely updated, it would be very nice if it is displayed on the map and taken into account when plotting the route. Additionally, it can be simply described on the “News” tab.
On the waiting time of trains I will stop separately. If you look at the
description of the online version of Yandex. Metro , then it says:
3. What exactly is the time and why is it approximate?
It is considered travel time between stations, the transition time from line to line. The time of descent or ascent along the escalator at the initial and final stations is not taken into account. For transitions and passages, the average time is taken, and for various reasons it may differ from real time for a couple of minutes (for example, the train did not arrive on time or there were a lot of passengers at the crossing).
7. Where do the route calculation data come from?
For calculation of routes data of the MMetro program Konstantin Shtennikov are used.
If someone has not seen the MMetro program, then when selecting a route, you can set the waiting time counting mode: do not take into account day or evening and 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 two stations. The waiting time of the train is not considered at all. That is, "the train did not arrive on time" from the third paragraph means that "you came, but there is no train." Long waiting times in the evenings require routing with a minimum of transfers. Considering this, an obvious cunning is traced in the second answer: “The route proposed by us will appear on the diagram, and the panel to the right of the diagram will describe in detail how to drive and how long the journey will take.” It is more correct to write about the “optimistic route” or honestly about the “route without waiting time”.
The Android version of Yandex.Metro uses the same data. I’ll quote from Ami Meio user dated January 2, 2013: “The new metro stations are already open on the 5th day, but they are still not on the diagram (and the program always lies about the trip time.” The description on Google Play reads:
Finding the best route in the subway. 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 the travel time with regard to transfers. And Metro will tell you which part of the train is better to sit down in order to get faster.
In the Yandex.Metro mobile application there is:
- automatic construction of the optimal route;
- calculation of travel time;
- replenishment of the travel ticket "Plantain" (St. Petersburg);
- and also, if your phone supports NFC (Galaxy Nexus, Google Nexus S, Sony Xperia S and HTC One X models), then with the help of 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 travel time. This is, of course, trifles, but the application is not only an apk-file, but also a description on the site. My eyes caught the following: (a) the absence of a space after the first sentence; (b) in the second sentence, the word Internet is written with a lowercase letter; (c) in the second sentence, it is not clear whether you can use an application or the Internet during a trip; (d) first words are written without using the letter “” (“accounting”, “more”), and then the letter “” appears in the word “calculation”; (e) the last sentence says “Moscow Metro”.
It is not entirely clear how the phrase “The application does not require an Internet connection” correlates with the required permissions:
Unlimited Internet access
Allows the app 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 does not have to be granted.
Connect / Disconnect Wi-Fi Network
Allows the app to connect to and disconnect from Wi-Fi access points, as well as to change the Wi-Fi network configuration on the device.
Change network settings
Allows the app to change the network connection status.
Most often, I run Yandex.Metro to find out which part of the train I should sit in to get closer to the desired transition or exit. This is a very good idea. Unfortunately, there are comments on the implementation. First, it is quite difficult to determine the specific car number based on the image. I can assume that the five cars designate: the first car, the beginning of the train, the center, the end of the train and the last car. It is possible that it would be slightly 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 cars is that at many stations there are fences, because of which the exit from the first car turns into a bypass of the barrier through the center of the hall. I tried to get there faster, and then, on the contrary, I lose time. Why not adjust the settings?
When traveling to a specific address, one of the problems is determining the desired output. If the only way out, 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 on the subway. But the final touch was blurred. Look at the screenshot.
We need to get to the metro station Tulskaya, but we are led to the center of the station, and not to one of the entrances to the station (indicated by the letters "M" at the top left and bottom). 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 do not know what it does. It is believed that the interface should be understandable. Why not give additional information about program objects?The only “information” document available in the program is a license agreement . I have a question about clauses 5.1 and 5.2:5.1. , « », , .
5.2. , . 5.1, .
I have turned off the standard Android “location” function and the Maps application refuses to determine my location. There are no additional options in the Yandex.Metro settings.
But Yandex.Metro continues to find the nearest metro station. That is, there is a violation of the license agreement on the part of Yandex (or simply lies)? The situation is similar with the agreement on the Yandex.Maps program , where the location is stated only in clause 5.3:5.3. , « » , GPS-, , , sim- , , .
But even with the "Report traffic jams" function disabled, the program continues to show the current location (the standard Android function is still off).Hiding with the help of AS-IS, companies can irresponsibly release software products of any quality. Foolishness is not punished until People hawala, you can do everything "stand back."Conclusion
It is enough to “turn on the brain” in the development and testing to improve the software product. Try to think like a user, put yourself in his place. If not, then find a typical user and talk to him. To feel the desires of the client should not only the task director, but the whole team. A quality product gives joy not only to the user, but also to you. I hope that this article will be useful.Addition. From Wolfram | Alpha, the answer came 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 task 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 this anyway,” “no one makes such mistakes,” etc.Secondly, everyone makes mistakes, including me. Specifically began an article with a sentence to read the chapter “Studying famous (and not very famous) mistakes” about “stupid” mistakes that cost dearly. The main question in relation to their work and the desire to make a quality product. It's not so hard to get better.