Как я могу просмотреть свой собственный код? [закрыто]


177

Я работаю над проектом в одиночку и должен поддерживать свой собственный код. Обычно проверка кода выполняется не автором кода, поэтому рецензент может взглянуть на код свежим взглядом - однако у меня нет такой роскоши. Какие методы я могу использовать для более эффективного просмотра моего собственного кода?


34
Я не уверен, что вы можете, по крайней мере, неэффективно - вы можете собрать команду рецензентов на codereview.stackexchange.com, если ваш код не является собственностью
jk.

8
Вы не можете просмотреть свой собственный код. Если вы не можете привлечь других людей, я бы посоветовал вам лучше всего использовать как можно больше статических анализаторов и включить ВСЕ предупреждения.

136
Обзор вашего собственного кода очень прост. Напиши кусок кода. Отойдите на 2 недели / месяцы / годы, продолжая изучать и разрабатывать другое программное обеспечение. Вернитесь к этой части и попытайтесь понять, что делает код. Вы знаете, что чему-то научились, когда думаете: «Что за идиот написал это ?!».
Юрий Зубарев

6
@YuriyZubarev Но что, если вы не хотите ждать недели / месяц / годы?
anatoliiG

12
Вы можете просмотреть свой код в измененном состоянии ума. Или вы можете кодировать в измененном состоянии ума и поручить проверку кода вашему обычному скучному я.
SK-logic

Ответы:


92

Прежде всего, используйте инструменты, чтобы проверить как можно больше. Тесты (подкрепленные некоторым разумным охватом кода) придадут вам уверенность в правильности кода. Инструменты статического анализа могут поймать множество лучших практик. Тем не менее, всегда будут проблемы, над которыми вам нужно разобраться человеческими глазами, и вы никогда не сделаете такую ​​же хорошую работу по рассмотрению ваших собственных вещей, как кто-либо другой, однако вы можете кое-что сделать, чтобы помочь

  • проверочные тесты существуют и проходят (возможно, имеют целевое тестовое покрытие, хотя в некоторых случаях вам может потребоваться прервать его, но вы должны быть в состоянии объяснить, почему)
  • проверьте прохождения статического анализа (здесь также будут ложные негативы, но это хорошо, если вы можете обосновать, почему тогда их лучше подавлять)
  • ведите контрольный список других вещей, которые нужно проверить в обзоре (в идеале добавьте это как новые правила статического анализа, если это возможно), убедитесь, что вы проверяете все, что SA не может проверить, например, являются ли комментарии по-прежнему действительными, правильно ли названы вещи ( конечно, одна из 2 сложных проблем, известных информатике)
  • если обнаружена неисправность, проверьте, является ли причина системной, и посмотрите, почему она не была обнаружена в предыдущих тестах или обзорах.

Это, конечно, полезно, когда вы просматриваете чужой код.


3
Что касается контрольного списка, наличие спецификации очень полезно.
Уэйн Вернер

Я не люблю контрольные списки. Они заставляют рецензента сосредоточиться на контрольном списке, а не думать о проблеме, решении и многом другом. Поэтому я предлагаю сделать их минимальными.
Балог Пал

57

Загляните на сайт Code Review Stack Exchange. Он предназначен для обмена кодом из проектов, над которыми вы работаете, для экспертной оценки :

Stack Exchange - это сайт вопросов и ответов, где вы можете получить рецензирование вашего кода. Мы работаем вместе, чтобы улучшить навыки программистов по всему миру, принимая рабочий код и улучшая его.

Если вы ищете отзывы о конкретном рабочем фрагменте кода вашего проекта в следующих областях…

  • Лучшие практики и использование шаблонов проектирования
  • Проблемы с безопасностью
  • Представление
  • Корректность в непредвиденных случаях

Вы также можете использовать инструменты статического анализа кода для обнаружения определенных типов проблем, но в некоторых случаях они будут вызывать ложные тревоги и не могут подсказать, как улучшить дизайн.


2
Это отличный ответ на вопрос «Как проверить мой код» и хороший совет в целом (я обязательно сделаю это), но все же немного оффтоп.
Макс Янков

5
Мне обычно не нравится ответ из 5 слов, но этот просто так правильно .
maple_shaft

20
В лучшем случае это только ограниченное решение. Постоянно помещать весь свой ежедневный выпуск в CR.SE не представляется возможным, так как большая часть этого будет довольно приземленным стандартным кодом. CR.SE также не сильно поможет в обнаружении проблем, которые требуют нетривиального понимания всей архитектуры приложения или предметной области, для которой написано приложение. С неофициальной точки зрения посмотрите на коллегиальный код, когда он проверен в стиле, обзоры, где я работаю, такого рода ошибки, вероятно, более распространены, чем те, которые были бы пригодны для отлова через CR.SE.
Дэн Нили

3
Реальная ценность в рецензировании - это получение фрагментов кода, которые вы никогда не представляли бы, если бы какая-либо проблема была обнаружена и выделена как неочевидная, не требующая объяснения или даже не логически правильная . Вы не можете опубликовать фрагмент, code reviewесли вы еще не знаете, что это проблематично.
ZJR

3
@ZJR Хорошо, код в ваших проектах проверен на 100%? Если да, у ваших инженеров слишком много свободного времени. Что касается вашего второго комментария, я не вижу проблем в запросе проверки кода в коде, который вы считаете идеальным.
BЈовић

29

Я разработал несколько совершенно разных людей в моей голове. Один из них даже не программист! Мы общаемся, обсуждаем последние новости и проверяем код друг друга.

Я настоятельно рекомендую мой подход.

ps он не шутит.


27
Меня зовут Билл, Джефф, Боб и Алиса, и мы одобряем это сообщение.
Майкл К

22

Я согласен с мнением JK, что обзор от одного человека не так эффективен, как обзор от двух человек. однако вы можете попытаться извлечь максимум из этого:

краткосрочный обзор (вскоре после написания кода)

Я использую Git в качестве локального хранилища. Всякий раз, когда я заканчиваю функцию или исправляю ошибку, я передаю изменения в хранилище.

Прежде чем я проверяю, я сравниваю то, что я изменил в своем коде, и переосмысливаю:

  • имена переменных / методов / классов по-прежнему отражают то, для чего они используются?

долгосрочный обзор (6 месяцев после написания кода)

Я спрашиваю себя:

  • я могу описать в одном предложении, что делает класс / метод / переменная?
  • Насколько легко использовать класс изолированно (без других классов) или написать юнит-тест?

4
+1 за предложение по краткосрочному обзору. Использование git для просмотра всех изменений между различными моментами времени действительно может помочь в очистке кода.
Лев

Мне нравится идея долгосрочного обзора, я думаю, что, вероятно, я бы объединил ее в общий обзор проекта, и, возможно, не рассмотрю весь код (опять же, я не склонен заниматься индивидуальной разработкой)
jk.

Я пытаюсь сделать что-то промежуточное: пересмотреть мой код примерно через месяц. Мне также нравится 6-месячный обзор.
Дэвид Дж

18

Во-первых, отложите ваш код настолько долго, насколько это практически возможно. Работайте над чем-то другим, другим фрагментом кода. Даже через день вы будете поражены тем, что найдете.

Во-вторых, документируйте свой код. Многие программисты ненавидят документировать свой код, но заставляют себя сесть и написать документацию, как использовать код и как он работает. Глядя на ваш код по-другому, вы найдете ошибки.

Говорят, что истинное владение предметом - это способность обучать его кому-то еще. С документацией вы пытаетесь научить кого-то другому свой код.


15

Преобразуйте эту технику отладки в технику проверки кода: http://en.wikipedia.org/wiki/Rubber_duck_debugging

Эта концепция творит чудеса, помогая вам выработать правильное мышление для работы с кодом, как если бы он был новым.


3
Я считаю, что техника утки была независимо изобретена в нескольких местах; вот отличная история об этом: hwrnmnbsol.livejournal.com/148664.html
Рассел Борогове

10
В наши дни моя резиновая утка - это форма вопросов и ответов на Stack Exchange. Желание написать хороший вопрос делает свое дело.
Кевин Рейд

Отличный совет. Это даже лучше, так как у меня уже есть резиновая утка на моем столе (она была здесь в качестве модели для одного из моих игровых персонажей, но я думаю, это не будет возражать против дополнительной работы ИТ-консультанта).
Макс Янков

5
@KevinReid, я люблю , чтобы увидеть некоторые статистические данные о заброшенных сообщениях SE - особенно те , которые люди печатали дольше , чем 60 - й года на. Я знаю, что сделал то же самое сам по крайней мере 5 раз.
Уэйн Вернер

Вах! Я не знал, что это «вещь». Я только что прокомментировал выше, что мой профессор-компьютерщик рекомендовал это во время нашей первой лекции, десятилетия назад. Он порекомендовал кошку, но, думаю, подойдет резиновая утка. Одно можно сказать наверняка, это не работает без антропоморфного кореша :-)
Mawg

13

В дополнение к полезным инструментам, упомянутым в других ответах, я думаю, что изменение вашего мышления полезно при проверке кода. Это глупо, но я говорю себе: «Я надеваю шляпу для проверки кода». Я делаю то же самое с QA.

Тогда важно ограничить себя этим мышлением. Вы либо рецензент, либо рецензент, вы не можете быть одновременно обоими. Поэтому, как рецензент, я делаю объективные заметки, чтобы поделиться с рецензентом. Я не изменяю код во время просмотра, это не то, что должен делать рецензент.

Формальность иногда кажется немного абсурдной, но, работая соло, я обнаруживаю, что меня часто тянет во многих направлениях. Так что я не обязательно могу замкнуть цикл проверки, прежде чем что-то еще возникнет - эта формальность (и на самом деле я говорю грубые заметки в вики-инструменте) полезна для того, чтобы убедиться, что обзор завершен. Точно так же, с моей шляпой QA, я добавляю билеты на ошибки, прежде чем исправить их.


Я не думаю, что можно пересмотреть свой собственный код
BЈовиЈ

4
@VJovic - я не думаю, что я выполняю наилучший из возможных проверок кода, но обычно я нахожу вещи, которые можно улучшить. Я тоже читал много чужого кода. Моя точка зрения на то, как выглядит «хороший» код, постоянно развивается. Я смущен кодом, который я написал несколько лет назад. Это ничем не отличается от проверки собственной статьи - это требует практики и гораздо больше усилий, но это выполнимо. Самая важная вещь, которую я не могу пересмотреть - это если абстракция имеет смысл для кого-то другого. Но я могу спросить себя, как сделать что-то проще, нужно ли это и т. Д.
Стив Джексон

@VJovic - Как упоминал ThomasOwens, вы также можете создать контрольный список из ошибок прошлого и пройти через него довольно объективно. Это еще одна приятная вещь - быть формальной в этом отношении: вы можете увидеть, что вы пропустили во время обзора, и соответствующим образом скорректировать свой процесс. Я обнаружил, что извлекаю много уроков, отслеживая себя и прилагая усилия, чтобы изменить свой подход, когда это указано.
Стив Джексон

3
Понимание правильного мышления действительно важно. Я считаю, что это помогает, если я действительно распечатываю код и просматриваю его на бумаге маркером. Тогда я не могу ничего изменить при просмотре (что мешает мне перейти в режим кодирования) и могу легко набрасывать комментарии и стрелки на бумаге.
Лев

Это означает пересмотр старого кода, а не нового. Для этого вам нужно набраться опыта, что может занять много времени.
BЈовић

9

Кажется, общее мнение таково, что самоанализ не эффективен. Я не согласен, и я думаю, что самоанализ может уловить много проблем, если все сделано тщательно.

Вот советы из моего нескольких лет опыта:

  • Имейте грубый контрольный список под рукой. Это то, что вы хотите пометить во время чтения вашего кода.
  • Возьмите ваш обзор кода в автономном режиме. Это может показаться расточительным, но возьмите распечатки, которые вы можете аннотировать и переворачивать назад или вперед, или цифровой эквивалент красиво выделенных PDF-файлов, синхронизированных с iPad, который затем переводится в автономный режим. Отойди от своего стола, чтобы все, что ты делаешь, проверяло твой код без отвлечения.
  • Делайте это рано утром, а не до конца рабочего дня. Свежая пара глаз лучше. На самом деле, это может помочь отойти от кода за день до его повторного просмотра.

Просто к сведению - эти рекомендации были частью рекомендаций в Oracle несколько лет назад, когда я работал там, где целью было выявить ошибки «вверх по течению» до того, как код был запущен в тестирование. Это очень помогло, хотя многие разработчики считали его скучной работой.


3
Я также добавил бы «подождите 24 часа», чтобы вы не смотрели код, который вы только что написали. Убедитесь, что ему по крайней мере 1 день, поэтому вы видите его после того, как вы спите всю ночь и не трогаете его в течение 24 часов.
Джефф Этвуд

Я часто использую распечатки, когда мне нужно пересмотреть или, особенно, рефакторинг некоторого кода. Это творит чудеса для меня.
Ицньютон

Как в каком-то фильме, который мы узнали из GB, поддельный оргазм лучше, чем отсутствие оргазма - самоанализ лучше, чем ничего. Да, вы можете много тренироваться, чтобы делать резиновые удары. Но это все еще весьма неэффективно по сравнению с фактическим экспертным обзором. особенно, если какое-то время не знакомиться с действительно хорошими рецензентами, чтобы подобрать методы.
Балог Пал

8

Техника обработки персонального программного обеспечения для проверок может быть полезной, хотя она основана на исторических данных о вашей работе и качестве продуктов.

Вы начинаете с исторических данных о ваших рабочих продуктах, в частности, о количестве и типах дефектов. Существуют различные методы классификации дефектов, такие как этот из курса PSP . Вы можете развивать свои собственные, но идея в том, что вы должны быть в состоянии сказать, какие ошибки вы делаете на своем пути.

Как только вы узнаете, какие ошибки вы делаете, вы можете разработать контрольный список, который вы сможете использовать во время проверки. Этот контрольный список будет охватывать основные ошибки, которые вы делаете, которые, по вашему мнению, лучше всего могут быть обнаружены в обзоре (в отличие от использования какого-либо другого инструмента). Каждый раз, когда вы просматриваете рабочий продукт, используйте контрольный список и ищите эти ошибки или ошибки, документируйте их и исправляйте. Периодически пересматривайте этот контрольный список, чтобы убедиться, что вы сосредоточены на реальных, актуальных проблемах в вашем коде.

Я также рекомендовал бы использовать поддержку инструментов, когда это имеет смысл. Инструменты статического анализа могут помочь найти некоторые дефекты, а некоторые даже поддерживают проверку стиля для обеспечения согласованности и хорошего стиля кода. Использование IDE с дополнением кода и подсветкой синтаксиса также может помочь вам предотвратить или обнаружить некоторые проблемы до того, как вы нажмете «построить». Модульные тесты могут охватывать логические проблемы. А если ваш проект достаточно большой или сложный, непрерывная интеграция может объединить все это в регулярно выполняемый процесс и создавать для вас хорошие отчеты.


7

Работать в одиночку означает, что, если вы не доверяете совершенно незнакомым людям для проверки кода от вашего имени, вам нужно будет смотреть на то, как вы пишете свое программное обеспечение, чтобы поддерживать качество кода.

Во-первых, у вас должны быть средства для обеспечения того, чтобы ваш код соответствовал требованиям, и, во-вторых, ваш код будет относительно легко изменить, если вы позже решите, что у вас что-то не так. Мое предложение состоит в том, чтобы применить подход, основанный на поведенческом развитии, по следующим причинам:

  1. BDD означает сначала писать тест кода. Это гарантирует, что весь ваш код покрыт тестами.
  2. BDD - это, по сути, TDD, но с немного другим фокусом и «языком». Это означает, что вы постоянно рефакторизируете свой код во время работы над ним и используете свои тесты, чтобы убедиться, что ваши усилия по рефакторингу продолжают гарантировать, что ваш код удовлетворяет спецификации вашего продукта.
  3. Язык BDD рекомендует писать тесты в форме операторов, которые по существу кодируют требования как модульные тесты.

Итак, идея в том, что ваш постоянный рефакторинг кода даже после того, как вы пройдете тестирование, означает, что вы эффективно просматриваете свой собственный код и используете свои модульные тесты в качестве «дополнительной пары глаз», которая гарантирует, что ваш код не работает. t отклоняться от требований, которые закодированы в тестах. Кроме того, высокий охват тестированием, основанный на требованиях, гарантирует, что вы сможете изменить свой код в будущем, не нарушая требований.

Реальная проблема для вас будет в том, сможете ли вы обнаружить потенциальные проблемы в вашем коде, которые будут указывать на необходимость рефакторинга. На рынке есть несколько инструментов для профилирования, которые могут помочь вам в этом, а также несколько других инструментов, связанных с показателями качества кода. Они часто могут рассказать вам о многих вещах, которые могут пропустить обзоры кода, и они необходимы при разработке проектов самостоятельно. В действительности, однако, ключом является опыт, и если вы привыкли быть беспощадными в своем рефакторинге, вы, вероятно, станете гораздо более критичны в отношении своего собственного кода. Если вы еще этого не сделали, я бы посоветовал почитать книгу Рефакторинга Мартина Фаулера в качестве отправной точки и найти хороший BDD API, который, по вашему мнению, будет работать для вас на любом языке, с которым вы решили работать.


5

Всякий раз, когда я находился в той же ситуации, что и вы, я пытался решить проблему «быть слишком близко к коду, чтобы объективно его исследовать», используя инструменты анализа кода / метрики. Само собой разумеется, что инструмент не может дать ту же ценность, что и опытный рецензент, но вы все равно можете использовать его для определения областей плохого дизайна.

Одним из инструментов, который я нашел довольно полезным в этом отношении, был SourceMonitor . Это немного упрощенно, но дает хорошее среднее мнение о вашем коде, например, о количестве методов в классе и сложности каждого метода. Я всегда чувствовал, что этот тип информации был столь же важным (если не более важным, чем) применение стилей кодирования с помощью таких инструментов, как StyleCop и т. Д. (Которые важны, но часто не являются источником самых больших проблем). Используйте эти инструменты с обычными заявлениями об отказе: знайте, когда нарушать эмпирическое правило, и что-то зеленое в инструменте метрики кода автоматически не дает хорошего качества.


5

Я не могу сказать вам, сколько раз я объяснял что-то рецензенту, и лампочка в моей голове включается и говорит: «Эй, подожди минутку». Поэтому я часто нахожу свои ошибки в обзоре кода, которые другой человек не видел. Так что вы можете попробовать это, просто начните объяснять код, как если бы рядом с вами сидел человек, который пытался понять, что вы сделали и почему.

Еще одна вещь, которую я часто нахожу в обзорах кода, заключается в том, что разработчик фактически не следовал этому требованию. Так что сравнение вашего кода и того, что он делает с фактическим требованием, является хорошей проверкой.

Мы часто делаем такие вещи, как пакеты служб SSIS, которые имеют аналогичные структурные потребности - для проверки кода я разработал контрольный список проверяемых вещей (правильна ли конфигурация, настроено ли ведение журнала, использует ли она базу данных метаданных, находятся ли файлы в стандартном расположении, и т.д.). У вас могут быть некоторые вещи, которые также будет полезно проверять каждый раз в обзоре кода. Сядьте и подумайте, что бы вы добавили в контрольный список того, что вы хотите проверить в своем обзоре кода (первый пункт, убедитесь, что требование выполнено, следующий элемент может иметь отношение к ошибкам перехвата и регистрации). По мере того, как вы делаете ошибки и исправляете их, вы можете добавлять другие элементы в список (скажем, что-то вроде: перейти ли к следующей записи в цикле или я собираюсь бесконечно повторять один и тот же первый элемент - потребуется всего один бесконечный цикл, чтобы научить вас искать это!).


1
Как Патрик Хьюз предлагает в своем ответе, использование прокси-сервера, например, резинового утенка, в качестве рецензента помогает мышлению.
Рассел Борогове

5

Дайте ему 3 месяца, затем вернитесь и посмотрите на свой код. Я обещаю вам, если вы не можете найти что-то не так с этим (или вопрос, кто написал этот мусор!), Вы лучше, чем я!


Это тоже моя техника. 3 месяца - это достаточно долго, чтобы все, что я не могу сразу понять, нужно было упростить или документировать лучше, но достаточно коротко, чтобы я все еще помнил, что происходит, чтобы легко исправить это.
Эрик Пол

5

Я обычно распечатываю весь свой код, сажусь в спокойной обстановке и читаю его, я нахожу множество опечаток, проблем, вещей, которые нужно реорганизовать, убирая при этом. Это хорошая самопроверка, которую, я думаю, должен сделать каждый.


Хорошее дополнение к совету выше, спасибо - хотя я думаю, что планшет или что-то подобное (с редактором, но без среды разработки) тоже будет работать. Интересно, кто отказался от этого и почему.
Макс Янков

4

Еще в колледже я был репетитором письма. Это, безусловно, дало мне некоторые перспективы в кодировании, которые, я думаю, многие разработчики никогда бы не подумали. Одним из наиболее важных является чтение вашего кода вслух. Это звучит не так уж и много, но я приведу прекрасный пример, который, я думаю, каждый может иметь отношение.

Вы когда-нибудь писали электронное письмо или статью, перечитывали несколько раз, чтобы убедиться в их правильности, а затем отправляли их, только чтобы обнаружить, что у вас есть явная орфографическая ошибка, опечатка или грамматическая ошибка? Я сделал это вчера, когда попросил клиента нажать клавишу дерьма вместо клавиши Shift. Когда читаешь в голове - видишь то, что хочешь увидеть.

Это сокращение для предложений «просто подождите день, неделю или месяц», которые сделали другие. Если вы читаете это вслух, вы ловите те же вещи. Я не знаю, почему это так эффективно, но, посидев с сотнями студентов и прочитав их вслух, все, что я могу сказать, это то, что это работает.


+1 Это согласуется с подходом «объясни своей кошке». Использование разных частей вашего мозга может быть полезным, когда вы не можете использовать коллегу.
BMitch

плюс один для ключа дерьма
Mawg

3

Большинство людей склонны рассматривать свой код как своих собственных детей и кормить их эго, а не реальностью. Как и любые другие обзоры кода, просматривайте его, когда видите чужой код. Полностью забудь, что ты что-то написал. Просмотрите каждую строку кода. Контрольный список был бы полезен для того, чтобы быть эстетическим в рассмотрении собственного кода. Автоматизированные инструменты для проверки кода могут помочь в некоторой степени. Я использовал некоторые инструменты, такие как klocwork (коммерческое программное обеспечение). Это очень полезно, когда вы работаете в больших проектах, и несколько разработчиков работают над этим. Всегда сосредотачивайтесь на обнаружении дефектов, а не на исправлении.

Но лучшей практикой было бы проверить себя, а затем привлечь к проверке как минимум двух других людей с выдающимися ролями.


3

Подумайте о том, чтобы провести инспекцию Фагана самостоятельно - вам придется адаптировать процесс, потому что вы сами, но вы должны быть в состоянии извлечь немало пользы из него. Хитрость заключается в том, чтобы найти правильный «набор правил» для оценки вашего кода как отдельного разработчика, а затем иметь дисциплину, чтобы каждый раз задавать эти вопросы в критическом, аналитическом, беспощадном настроении. Я подозреваю, что вы можете начать с мозгового штурма своих 4-5 важных вопросов, а затем развить их со временем. Некоторые люди против формальных инспекций, потому что они кажутся такими трудоемкими ... прежде чем вы решите, что они слишком дороги, имейте в виду все статистические доказательства того, что проведение инспекций должным образом фактически сокращает время проекта. Вот ссылка на Википедию, с которой вы можете начать дальнейшие исследования:

http://en.wikipedia.org/wiki/Software_inspection

Также было несколько книг, например, Google для «Процесса проверки программного обеспечения» Штрауса и Эбенау.

Другой вариант - заплатить кому-то за проверку важного проекта или, возможно, иногда платить ему за проверку всего вашего кода. Этот парень довольно хорош, мы несколько раз с ним летали тренировать наших новых разработчиков:

http://www.javaspecialists.eu/


0

Помимо всех рекомендаций по проверке кода, вы можете использовать такие инструменты, как PMD и findBug, чтобы сделать первый уровень здравомыслия для вашего кода.


0

На самом деле это еще не было включено в ответ (но было добавлено как комментарий к существующему ответу)

Просмотрите код после хорошего ночного сна, например, начните день с просмотра кода, который вы написали в предыдущий день.

Это, конечно, не даст вам коллективного опыта команды, но даст вам возможность пересмотреть код с новой точки зрения.

Например, если вы оставили кусок кода с неприятным хаком, вы, возможно, не будете слишком склонны его исправлять, если вы пересмотрите свой код сразу после этого. В конце концов, когда вы начинаете просматривать свой код, вы уже знаете и принимаете наличие этого хака. Но если вы хорошо спали ночью, вы, вероятно, более заинтересованы в поиске лучшего решения.

Когда мы спим, мозг на самом деле не перестает работать над проблемами, которые у нас есть, так что вы можете действительно найти решение там, хотя эти решения иногда могут показаться странным образом .

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.