Изменения

м
Строка 1: Строка 1: −
{{Заготовка}}
+
{{Устарело}}
''Это 19 глава перевода оригинального руководства по Dream Maker от разработчиков.''
+
Данная статья не совсем соответствует действительности и нуждается в новом переводе.
 +
 
 +
''Это 19 глава перевода оригинального руководства по Dream Maker от разработчиков. Если вы работаете в Dream Maker - внимательно прочтите её и сообщите о найденных ошибках.''
    
[http://wiki.ss13.ru/index.php?title=All_about_the_code Остальные главы руководства и статьи о программировании на коде BYOND от любителей на русском.]
 
[http://wiki.ss13.ru/index.php?title=All_about_the_code Остальные главы руководства и статьи о программировании на коде BYOND от любителей на русском.]
Строка 215: Строка 217:  
Fortunately, most programming tasks do not require exponential complexity. With a good design, you can split the project into pieces which interact with each other in a fairly simple way. These pieces are often called modules which is why this practice is termed modular programming. (It is interesting to note, however, that all such schemes to avoid exponentially complex code ultimately fail. They only move the exponential growth to a higher level--from individual statements to procedures to objects and on and on. It may be true that complexity will always win out in the end and that every project undergoing perpetual growth must periodically be redesigned from scratch in order to remain comprehensible. Or perhaps this tendency is merely the result of a periodic increase in wisdom to offset the inevitable decline in intelligence. In my own case, I know this to be a prominent factor.)-->
 
Fortunately, most programming tasks do not require exponential complexity. With a good design, you can split the project into pieces which interact with each other in a fairly simple way. These pieces are often called modules which is why this practice is termed modular programming. (It is interesting to note, however, that all such schemes to avoid exponentially complex code ultimately fail. They only move the exponential growth to a higher level--from individual statements to procedures to objects and on and on. It may be true that complexity will always win out in the end and that every project undergoing perpetual growth must periodically be redesigned from scratch in order to remain comprehensible. Or perhaps this tendency is merely the result of a periodic increase in wisdom to offset the inevitable decline in intelligence. In my own case, I know this to be a prominent factor.)-->
    +
Понятие модуля применимо не только к какой-либо части кода, а чаще подразумевает файл или группу файлов. Открытая часть модуля - процедуры, переменные и объекты, свободные для использования в других местах помимо самого модуля. Закрытая часть модуля - это собственно тело самого модуля, сам код, который однокомпонентен.
 +
 +
При разработке большого проекта, хотя бы один из участников(а желательно все) должен быть ознакомлен с тем, что делает каждый из написанных модулей и какое у него применение. Хорошим тоном считается делать простое и понятное описание и название для каждого модуля.
   −
Although the term module can refer to any unit of code, it most often is embodied by a file or group of files. The public parts of the module are those procedures, variables, and object types which are advertised for use by code outside the module. This is called the module interface and defines the syntax for putting information in and getting results out of the module. All other private material is considered internal to the module and is not for use by outside code.
+
<!--Although the term module can refer to any unit of code, it most often is embodied by a file or group of files. The public parts of the module are those procedures, variables, and object types which are advertised for use by code outside the module. This is called the module interface and defines the syntax for putting information in and getting results out of the module. All other private material is considered internal to the module and is not for use by outside code.
   −
When devising a project, one should foresee the function of the different component modules and have a rough idea of the interface to each one. When work commences on a module, it is worth putting a description of the public interface in a comment at the top of the file. This helps focus development along lines consistent with a good clean interface. You will also find it a useful reference in the future when you or someone else needs to use the module. You won't need to page through expanses of code to figure out how to operate your wonderful gadget.
+
When devising a project, one should foresee the function of the different component modules and have a rough idea of the interface to each one. When work commences on a module, it is worth putting a description of the public interface in a comment at the top of the file. This helps focus development along lines consistent with a good clean interface. You will also find it a useful reference in the future when you or someone else needs to use the module. You won't need to page through expanses of code to figure out how to operate your wonderful gadget.-->
      Строка 230: Строка 235:     
<!--There are a few cases, however, when the order of code does matter. The preprocessor, for example, operates strictly sequentially from top to bottom of the code. The principle consequence of this is that macro definitions must precede their use. This is one good reason to instead use constant variables for the purpose when it is possible.-->
 
<!--There are a few cases, however, when the order of code does matter. The preprocessor, for example, operates strictly sequentially from top to bottom of the code. The principle consequence of this is that macro definitions must precede their use. This is one good reason to instead use constant variables for the purpose when it is possible.-->
*  
+
* Последовательность кода важна при наследовании процедур или переменных объекта. Если какая-либо процедура повторяется несколько раз, то она наследует последовательность выполнения первого раза.
Another time when code sequence matters is when overriding object procedures or variable initializations. If the same procedure is overridden several times in the same object type, subsequent versions take precedence and will treat previous ones as their parent procedure.
+
<!--Another time when code sequence matters is when overriding object procedures or variable initializations. If the same procedure is overridden several times in the same object type, subsequent versions take precedence and will treat previous ones as their parent procedure.-->
 
+
Например, при добавлении дополнительных функций к процедуре client.Topic() в разных местах в коде случается эффект сочетания зачений в родительском элементе:
One might, for example, add functionality to the client.Topic() procedure in several different locations in the code. As long as you remember to execute the parent procedure each time, the additions are cumulative.
+
<!--One might, for example, add functionality to the client.Topic() procedure in several different locations in the code. As long as you remember to execute the parent procedure each time, the additions are cumulative.-->
    
client/Topic(T)
 
client/Topic(T)
   if(T == "introduction")
+
   if(T == "вступление")
       usr << "Once upon a time..."
+
       usr << "И вот как-то раз..."
 
   else ..()
 
   else ..()
    
client/Topic(T)
 
client/Topic(T)
   if(T == "help")
+
   if(T == "подсказка")
       usr << "The situation is helpless."
+
       usr << "Буквально позавчера."
 
   else ..()
 
   else ..()
As written, these two definitions of the Topic procedure can fall in any order with any amount of intervening code. If one of them neglected to call ..(), however, it would disable any previous versions of the procedure. It is therefore good practice to always call the parent procedure unless you specifically wish to disable it. Then you don't have to worry about maintaining any special order of the procedures.
+
В таком написании, эти два определения процедуры client/Topic(T) могут быть размещены в коде в любом месте. Если один из них будет выполнен и приведёт к значению ..() ,то другой уже не наступит. Вот в таких случаях и бывает полезно обращаться к процедуре-родителю
 
+
<!--As written, these two definitions of the Topic procedure can fall in any order with any amount of intervening code. If one of them neglected to call ..(), however, it would disable any previous versions of the procedure. It is therefore good practice to always call the parent procedure unless you specifically wish to disable it. Then you don't have to worry about maintaining any special order of the procedures.-->
 
  −
===Debugging Code===
     −
Bugs happen. Actually that is an understatement in large projects. Bugs happen frequently. This is fortunate, because there is nothing more satisfying than exterminating a bug.
      +
===Отладка кода===
   −
====Good Coding Habits====
+
Или иначе дебаггинг(debugging).
   −
The novice programmer has far too much faith in the compiler. The veteran bug hunter, however, knows that just because the code compiles doesn't mean it works. It could still be infested with potential problems.
+
====Манеры хорошего кодера====
   −
The first rule for successful debugging is to compile the code yourself. Of course you do not need to generate the byte code by hand; that's what the compiler is for. Compiling the code yourself means reading through the code you have written as though you were the compiler and making sure what the compiler sees matches what you intended.
+
Ошибка начинающих программистов в том, что они слишком полагаются на компилятор. Опытные баголовы и багоюзеры знают, что если код скомпилирован, то не факт что он работает как написано. Уязвимости бывают везде.
 +
<!--The novice programmer has far too much faith in the compiler. The veteran bug hunter, however, knows that just because the code compiles doesn't mean it works. It could still be infested with potential problems.-->
   −
The second good debugging habit is to run the code yourself. Initialize the necessary variables to some typical values and step through the procedure in your mind. The server can catch simple errors, but only you know what the code is supposed to do, so only you can tell the difference between code which runs and code which actually works. After doing a typical case, also be sure to think through any exceptional cases which may occur. For example, with a loop, you should verify that the first and last iteration will operate as expected.
+
Первый вызов для отладчика кода - суметь прочитать код и попробовать скомпилировать его в уме, так как его увидит машина. Возможно где-то не хватает переменных, возможно некоторые процессы ведут к нулевому значению, возможно некоторые условия невозможно выполнить в принципе. Думайте логически.
 +
<!--The first rule for successful debugging is to compile the code yourself. Of course you do not need to generate the byte code by hand; that's what the compiler is for. Compiling the code yourself means reading through the code you have written as though you were the compiler and making sure what the compiler sees matches what you intended.-->
   −
After doing these pre-checks, it is, of course, vital to test the code for real. This is known as beating on the code. Don't be gentle. Treat it roughly to expose any unforeseen weaknesses. If it is code which responds to user input, try doing the usual things and then try things you wouldn't normally expect.
+
Второй шаг - запустить код, так чтобы он заработал. Подставить необходимые переменные и запустить его в приложении. Сервер может выявить простые ошибки и баги, но только вы можете понять что работает не так, как оно должно работать, и почему это не так. А что работает именно так как описано в коде. Поиграйте с переменными и кодом, чтобы лучше понять механизмы компиляции и работы вашего кода.
 +
<!--The second good debugging habit is to run the code yourself. Initialize the necessary variables to some typical values and step through the procedure in your mind. The server can catch simple errors, but only you know what the code is supposed to do, so only you can tell the difference between code which runs and code which actually works. After doing a typical case, also be sure to think through any exceptional cases which may occur. For example, with a loop, you should verify that the first and last iteration will operate as expected.-->
   −
Code which has passed these three tests will be reasonably sound. By catching bugs early, you save yourself a lot of trouble, because the code is fresh in your mind and therefore easier to decipher. Besides, you will find that deciphering bug reports from other users can be even harder!
+
Затем проведите нагрузочное тестирование, попробуйте выйти за пределы допустимых параметров, указанных вами при создании объектов и фич для проекта. Как правило на этом этапе всплывают все баги и уязвимости в написанном и вы можете отловить их и пофиксить\оставить для рабочей версии проекта.
 +
<!--After doing these pre-checks, it is, of course, vital to test the code for real. This is known as beating on the code. Don't be gentle. Treat it roughly to expose any unforeseen weaknesses. If it is code which responds to user input, try doing the usual things and then try things you wouldn't normally expect.
    +
Code which has passed these three tests will be reasonably sound. By catching bugs early, you save yourself a lot of trouble, because the code is fresh in your mind and therefore easier to decipher. Besides, you will find that deciphering bug reports from other users can be even harder!-->
   −
====Elusive Bugs====
+
===="Неуловимые" баги====
    +
Существует два типа багов: Краш-баги которые останавливают процесс целиком (proc crashers) и мелкие баги(silent errors), которые ломают отдельные фичи. : Пример Краш-бага - обращение к переменной объекта, отсутствие ответа от объекта, придание переменной по умолчанию равной нулю, что приводит к завершению оператора.
 +
Когда крашится процедура, как правило сохраняются логи ошибки в world.log . При запуске созданного вами проекта в клиенте Dream Seeker, эта информация будет показана в отдельном окошке. При запуске проекта на сервере Dream Daemon - логи сохраняются в выводе серверной информации, либо в отдельном файле.
 +
<!--
 
Even when you have been careful, some subtle problems may still occasionally slip through. Hunting them down can be a frustrating experience, so it is good to have a few tricks up the sleeve.
 
Even when you have been careful, some subtle problems may still occasionally slip through. Hunting them down can be a frustrating experience, so it is good to have a few tricks up the sleeve.
    
There are two types of bugs: proc crashers and silent errors. Those that crash procs are the result of some exceptional case occurring. For example, the code might be trying to access an object's variable but the object reference is null. Allowing this sort of case to silently slide by (by pretending the variable of the non-existent object is null, for example) might be a convenient thing to do in some cases, but in others it might cover up a genuine error that needs to be corrected by the programmer. Crashing the procedure and reporting the problem therefore makes it much easier for you to discover the problem and find its source.
 
There are two types of bugs: proc crashers and silent errors. Those that crash procs are the result of some exceptional case occurring. For example, the code might be trying to access an object's variable but the object reference is null. Allowing this sort of case to silently slide by (by pretending the variable of the non-existent object is null, for example) might be a convenient thing to do in some cases, but in others it might cover up a genuine error that needs to be corrected by the programmer. Crashing the procedure and reporting the problem therefore makes it much easier for you to discover the problem and find its source.
   −
When the procedure crashes, some diagnostic information is output to world.log. When running the world directly in the client, this information is displayed directly in the terminal window. With a stand-alone server, it is normally in the server's output but may be redirected to a file.
+
When the procedure crashes, some diagnostic information is output to world.log. When running the world directly in the client, this information is displayed directly in the terminal window. With a stand-alone server, it is normally in the server's output but may be redirected to a file.-->
   −
The most important part of the diagnostic information is the name of the procedure that crashed. The value of the src and usr variables are also included. If there are any procedures in the call stack (that is, the procedure which called this one, and the procedure which in turn called it, and so on) these are displayed.
+
Самое главное - найти в логах название процедуры, которая вызвала падение выполнения кода, а также значение переменных src и usr на момент выполнения процедуры. Процедуры могут быть показаны цепочкой вызовов - будут показаны обращающиеся к этой и вызванной этой процедурой процедуры. 
 +
<!--The most important part of the diagnostic information is the name of the procedure that crashed. The value of the src and usr variables are also included. If there are any procedures in the call stack (that is, the procedure which called this one, and the procedure which in turn called it, and so on) these are displayed.
   −
If this is not enough information for you to locate the source of the problem, try compiling the world with the DEBUG macro defined. This will add source file and line number information to the diagnostic output.
+
Также вы можете воспользоваться макросом DEBUG, описанным выше для отлова багов и точным вычислением их месторасположения в коде исполняемого файла.
 +
<!--If this is not enough information for you to locate the source of the problem, try compiling the world with the DEBUG macro defined. This will add source file and line number information to the diagnostic output.
 +
Существует команда, способная показать вам какое именно значение переменной привело к падению кода. Вот она:
 +
<!--One may also need to probe around in the code to see what is going on. This can be accomplished by sending your own diagnostic information to world.log. For example, you might to know the value of a variable at a particular point in the code. This could be done with a line like the following:-->
   −
One may also need to probe around in the code to see what is going on. This can be accomplished by sending your own diagnostic information to world.log. For example, you might to know the value of a variable at a particular point in the code. This could be done with a line like the following:
+
world.log << "[__LINE__]: myvar = [myvar]"
   −
world.log << "[__LINE__]: myvar = [myvar]"
+
Отладка кода проводится как при отдельных случаях падения кода(и тогда удобнее пользоваться примерами приведёнными выше), так и по всем исполняемым строкам и файлам при финальной диагностике. В последнем случае вы можете пользоваться следующими макросами:
Sometimes debugging output such as this is simply removed after fixing the problem, but sometimes you may want diagnostic information to appear whenever you are testing the code. In this case, a macro such as the following may be useful.
+
<!--Sometimes debugging output such as this is simply removed after fixing the problem, but sometimes you may want diagnostic information to appear whenever you are testing the code. In this case, a macro such as the following may be useful.-->
    
: #ifdef DEBUG
 
: #ifdef DEBUG
Строка 287: Строка 302:  
: #define debug null
 
: #define debug null
 
: #endif
 
: #endif
You can then send output to debug and it will be ignored when not in DEBUG mode.
     −
Another tool for hunting bugs is to comment out code. This may be helpful when determining whether a certain piece of code is responsible for an observed problem. By simplifying the procedure and gradually disabling all but the code which causes the glitch, you can save yourself from scrutinizing a lot of irrelevant material.
+
Вывод информации на отладку будет осуществляться, но он будет игнорироваться до тех пор, пока вы не используете макрос #DEBUG.
 +
<!--You can then send output to debug and it will be ignored when not in DEBUG mode.-->
 +
 
 +
Есть полезный приём при поиске багов - вынести код в комментарии. Код, вынесенный в комментарий перестаёт восприниматься компилятором как исполняемые команды, зато виден разработчику. Это полезно для выделения кусков кода, ответственных за совершение ошибок при исполнении, и временном устранении их, вплоть до отладки проблемного места.
 +
<!--Another tool for hunting bugs is to comment out code. This may be helpful when determining whether a certain piece of code is responsible for an observed problem. By simplifying the procedure and gradually disabling all but the code which causes the glitch, you can save yourself from scrutinizing a lot of irrelevant material.
   −
This is also essential when asking others for help. Nobody wants to read through pages and pages of somebody else's code. If you can't see the problem yourself but can isolate it down to a small piece of code, you will find it much easier (and fruitful) when getting help from other programmers. Sometimes just trying to clearly define the problem enables you to suddenly see the solution yourself--avoiding the embarrassment altogether.
+
This is also essential when asking others for help. Nobody wants to read through pages and pages of somebody else's code. If you can't see the problem yourself but can isolate it down to a small piece of code, you will find it much easier (and fruitful) when getting help from other programmers. Sometimes just trying to clearly define the problem enables you to suddenly see the solution yourself--avoiding the embarrassment altogether.-->