Пишите код так как будто сопровождать его будет склонный к насилию психопат
Не зависимо от экономических подъемов и спадов хороших программистов всегда не хватает, а жизнь слишком коротка, чтобы тратить ее на работу в отсталом учреждении при наличии множества лучших вариантов.
Программисты склонны рассматривать менеджеров как низшую ступень технической эволюции, где-то между одноклеточными организмами и мамонтами, вымершими в ледниковый период.
Помните! Тестирование может указать только на наличие, но не отсутствие ошибок.
Похвалите себя за чтение этой книги. За это время вы продвинулись вперед гораздо дальше, чем большинство ваших коллег, потому что объем этой книги превышает годичный объем чтения большинства программистов.
Новые инструменты полезны, но они не заменяют ясность мышления.
Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете.
Абстракция — один из главных способов борьбы со сложностью реального мира.
«Когда вместе собираются критики, они говорят о Теме, Композиции и Идее. Когда вместе собираются художники, они говорят о том, где купить дешёвый скипидар».
Пабло Пикассо.
Если требования [к проекту] нестабильны, рассматривайте работу над ними как отдельный проект.
Джон Бентли говорит, что программист должен быть способен сесть у камина со стаканом бренди, хорошей сигарой, охотничьей собакой у ног и «сформулировать программу» подобно тому, как писатели создают романы.
Один из пионеров информатики Эдсгер Дейкстра обращал внимание на то, что компьютерные технологии — единственная отрасль, заставляющая человеческий разум охватывать диапазон, простирающийся от отдельных битов до нескольких сотен мегабайт информации, что соответствует отношению 1 к 109, или разнице в девять порядков (Dijkstra, 1989). Такое гигантское отношение просто ошеломляет. Дейкстра выразил это так: «По сравнению с числом семантических уровней средняя математическая теория кажется почти плоской. Создавая потребность в глубоких концептуальных иерархиях, компьютерные технологии бросают нам абсолютно новый интеллектуальный вызов, не имеющий прецедентов в истории». Разумеется, за прошедшее с 1989 г. время сложность ПО только выросла, и сегодня отношение Дейкстры вполне может характеризоваться 15 порядками.
«Планируйте выбросить первый экземпляр программы: вам в любом случае придется это сделать »
Фред Вруне
«Если вы планируете выбросить первый экземпляр программы, то выбросите и второй»
Крейг 3еруни
При инкрементной разработке вы сначала создаете самую простую версию системы, которую можно было бы запустить. Она может не принимать реальных данных, может не выполнять над ними реальных действий, может не генерировать реальные результаты — она должна быть просто скелетом, достаточно крепким,чтобы поддерживать реальную систему по мере ее разработки. Она может вызывать поддельные классы для каждой из определенных вами основных функций. Такая система похожа на песчинку, с которой начинается образование.
За ошибку, допущенную при создании простого объекта, приходится расплачиваться лишь потраченным временем и, возможно, некоторым разочарованием
Неудачное определение проблемы грозит пустой тратой времени на решение не той проблемы. Разумеется, нужную проблему вы при этом тоже не решите.
Думая о новой функции, клиенты приходят в возбуждение. Кровь у них разжижается, переполняет продолговатый мозг, и они впадают в эйфорию, забывая обо всех собраниях, посвященных обсуждению требований, о церемонии подписания и всех документах. Угомонить таких одурманенных новыми функциями людей проще всего, заявив: «Ого, это действительно прекрасная идея! Но ее нет в документе требований, поэтому я должен пересмотреть график работы и смету, чтобы вы могли решить, хотите ли вы реализовать это прямо сейчас или позднее». Слова «график» и «смета» отрезвляют куда лучше, чем кофе и холодный душ, и многие требования быстро превращаются в пожелания.
В свое время Данте отвел нижний круг ада самому Сатане.
Но с тех пор кое-что изменилось, и сейчас Сатана охотно делит нижний круг с программистами, не умеющими эффективно отлаживать программы.
Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живёте
. даже если проект не планируется развивать и вы не собираетесь делиться исходными кодами, потому что через 20 лет какой-нибудь маньяк будет изучать и дорабатывать машинный код вашего продукта, и он может захотеть вас найти.
Вообще я достаточно редко играю в компьютерные игры. Бывало, не играл по несколько лет подряд. Но иногда во мне просыпается маленький реверс-инженер, который мотивирует меня забраться в машинный код какой-нибудь любимой игрушки из прошлого. В последний год я занимался доработкой Need For Speed III: Hot Pursuit (1998 года). Это моя любимая игра в жанре, но теперь я, к своему сожалению, знаю о том, насколько отвратительно она написана. Большое количество маленьких багов в самых неожиданных местах — прямое следствие низкого качества кода.
Насколько всё плохо?
В исполняемом файле огромное количество кода, который остался в наследство от предыдущих частей игры и не используется, то есть устаревший код не удалялся разработчиками, причём мне встречались случаи, когда какой-то устаревший код вызывался, но результаты его работы игнорировались, потому что обновлённому коду они уже были не нужны. В игре всюду используются статичные массивы фиксированного размера, во многих случаях отсутствуют проверки выхода за пределы массива, что приводит к падениям, когда какого-то зарезервированного объёма памяти не хватает. В игре используется большое количество грязных хаков. Например, функция гонки по отражённому варианту трассы реализована не отражением модели трассы при её загрузке, а переворотом каждого кадра при рендеринге, с инверсией кнопок «лево» и «право» и ряда аналогичных подмен там, где разработчики не забыли добавить соответствующий код. Из-за этого надписи на машинах (например, копов) отражены, а во время гонок копы путают «право» и «лево» при переговорах по рации. Есть и ошибки, явно связанные с использованием магических чисел в коде вместо именованных констант, когда значение константы в процессе разработки было изменено, но остался код, который использует старое значение и работает неправильно. Но один случай оказался забавным настолько, что мне захотелось поделиться им в рамках небольшой заметки.
Сколько ошибок может быть в 4 вариантах одного и того же кода?
В игре присутствовал один незначительный баг, связанный с отступами в выпадающих меню. Например, если был выбран режим «Hot Pursuit», левый отступ всех верхних выпадающих списков значительно увеличивался без явной на то необходимости.
Я предположил, что это связано с ошибкой в коде, который добавляет пространство для вывода иконок прохождения в выпадающем списке трасс, которые как раз и должны отображаться только в режиме «Hot Pursuit».
Обычные выпадающие списки тоже имели проблемы с отступами в зависимости от режима, но не в такой явной форме. Поскольку я как раз копался рядом с соответствующим кодом, решил заодно исправить и это странное поведение.
Тут стоит отметить, что в коде игры не встречаются следы вещей вроде наследования, так что скорее всего она писалась на чистом C. В игре реализован код, который читает списки элементов меню и их свойства из внешних текстовых файлов, но разработчики часто ленились добавлять поддержку какого-то нового свойства, и писали дополнительный код, опираясь просто на имя элемента. Например, код вывода выпадающих списков сам проверяет название текущего элемента и какие-то другие переменные, и в зависимости от этого может применять какую-то дополнительную логику.
Так оказалось и здесь. Поскольку в меню используется два разных типа выпадающих списков (обычный и верхний), весь код работы с ними был целиком продублирован дважды. Помимо этого оказалось, что левый отступ выбирается разными фрагментами кода при вычислении левой и правой границы выпадающего списка. Итого — по идее у нас должно быть 4 копии одного и того же кода. Как бы не так!
Вариант 1 (при вычислении отступа левой границы обычной выпадашки):
На C это выглядело примерно так:
dw_padding = (stricmp(str_element_name, "tracks") == 0 && dw_cfg_race_type == 3) ? 35 : 15;
Вариант 2 (при вычислении отступа правой границы обычной выпадашки):
На C это выглядело примерно так:
dw_padding = (stricmp(str_element_name, "tracks") == 0 || stricmp(str_element_name, "rectrk") == 0) ? 35 : 15;
Варианты 3 и 4 (при вычислении отступа левой и правой границ выпадашки под заголовком):
На C это выглядело примерно так:
dw_padding = (dw_cfg_race_type == 3) ? 35 : 15;
Все варианты вместе (для наглядности):
dw_padding = (stricmp(str_element_name, "tracks") == 0 && dw_cfg_race_type == 3) ? 35 : 15; dw_padding = (stricmp(str_element_name, "tracks") == 0 || stricmp(str_element_name, "rectrk") == 0) ? 35 : 15; dw_padding = (dw_cfg_race_type == 3) ? 35 : 15;
Какой же вариант правильный? Ответ: ни один! Только если мы объединим все проверки вместе, мы можем получить единственно верный вариант кода, и выглядел бы он примерно так:
dw_padding = (dw_cfg_race_type == 3 && (stricmp(str_element_name, "tracks") == 0 || stricmp(str_element_name, "rectrk") == 0)) ? 35 : 15;
Итого у нас 4 варианта одного и того же кода, при этом в разных вариантах допущено 3 разные ошибки! Просто уникальный случай и отличная демонстрация того, почему копипаста — это плохая идея.
Как это было исправлено?
О том, как вносятся изменения в машинный код, я писал ранее. Для исправления проблемы я написал одну функцию:
Все приведённые выше фрагменты кода были заменены на вызов этой функции. Теперь отступы в списках выбираются правильно 🙂 И это лишь одно из более чем 200 изменений, которые были сделаны в патче. Описанное изменение на самом деле одно из самых маленьких, но зато сама ошибка, на мой взгляд, была интересной (как демонстрация вреда от соответствующего антипаттерна).
Выводы?
А теперь подумайте. Если здесь нашёлся самозванец, который взялся исправлять без спроса чужие баги в программе без исходных кодов, может найтись и тот, кто в итоге будет настолько зол, что у него появится желание отыскать разработчика или его родственников. А оно вам надо? Пишите качественный код 🙂
- reverse engineering
- need for speed iii
- Assembler
- Разработка игр
- Реверс-инжиниринг
- Разработка под Windows
Пишите код так как будто сопровождать его будет склонный к насилию психопат
Post by Vizit0r » 13.08.2010 22:35
тестеры нужны
«Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете». (с) Макконнелл, «Совершенный код».
Alexej Novice
Posts: 79 Joined: 06.06.2008 11:55 Contact:
Post by Alexej » 14.08.2010 19:55
столько всего нового добавлено
жаль не помогу потестить
Vizit0r Developer
Posts: 3958 Joined: 24.03.2005 17:05 Contact:
Post by Vizit0r » 14.08.2010 21:47
вот насчет тебя — очень жаль.
лучший тестер за все время
«Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете». (с) Макконнелл, «Совершенный код».
Vizit0r Developer
Posts: 3958 Joined: 24.03.2005 17:05 Contact:
Post by Vizit0r » 14.08.2010 22:13
сегодня был часик свободного времени, занялся одним вопросом, до которого руки не доходили — подключение своих классов к паскальскрипту.
еле успел, но успел — теперь из стелсовых скриптов доступен класс TIniFile со всеми сопутствующими.
var ConfIni : TIniFile; . ConfIni := TIniFile.Create('D:\Stealth\my\Stealth.ini'); LastUsedProfile := ConfIni.ReadString('General', 'Last profile', ''); ShowNonZeroSkills := ConfIni.ReadBool('General', 'Show nonzero skills', False); DefaultReconnectTime := ConfIni.ReadInteger('General','DefaultReconnectTime',120); ConfIni.Free;
Если у кого-то есть пожелания насчет доступности стандартных классов из скриптов — говорите, встрою.
На досуге сделаю пример создания из скрипта с нуля формы с парой работающих контролов, типа кнопки с реакцией.
«Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете». (с) Макконнелл, «Совершенный код».
Vizit0r Developer
Posts: 3958 Joined: 24.03.2005 17:05 Contact:
Post by Vizit0r » 16.08.2010 7:13
Vizit0r wrote: На досуге сделаю пример создания из скрипта с нуля формы с парой работающих контролов, типа кнопки с реакцией.
Program New; var PSForm : TForm; PSButton : TButton; PSCheckBox : TCheckBox; procedure ButtonClick(Sender : TObject); begin PSForm.Caption := 'You clicked the button'; ShowMessage('ggg'); end; procedure CheckBoxClick(Sender : TObject); begin PSButton.Enabled := not PSButton.Enabled; end; begin try PSForm := TForm.Create(Self); PSForm.Position := poScreenCenter; PSForm.Caption := 'Form from PascalScript'; PSForm.Width := 300; PSForm.Height := 140; PSButton := TButton.Create(Self); PSButton.Parent := PSForm; PSButton.SetBounds(8,8,75,25); PSButton.Caption := 'Test Button'; PSButton.OnClick := @ButtonClick; PSCheckBox := TCheckBox.Create(Self); PSCheckBox.Parent := PSForm; PSCheckBox.Left := 15; PSCheckBox.Top := 40; PSCheckBox.Caption := 'CheckBox'; PSCheckBox.OnClick := @CheckBoxClick; PSForm.ShowModal; finally if PSButton <> nil then PSButton.Free; if PSCheckBox <> nil then PSCheckBox.Free; if PSForm <> nil then PSForm.Free; end; end.
вота. Но не злоупотребляйте этим. очень уж этот экспорт какой-то глючный. Точнее, глюков нет, есть утечки памяти при работе с окнами и контролами из скрипта, которые при частых вызовах дают мутные ошибки, ведущие в никуда.
P.S. Есть версия, что ошибки возникают из-за того, что форма и все контролы создаются в потоке скрипта, а не в основном. но это исправляться не будет 100% — так надо.
Last edited by Vizit0r on 17.08.2010 21:13, edited 1 time in total.
«Пишите код так, как будто сопровождать его будет склонный к насилию психопат, который знает, где вы живете». (с) Макконнелл, «Совершенный код».
Не проходит решение
В классе Solution объявлено и проинициализировано публичное строковое поле. Но строка слишком длинная и неудобочитаемая.
Для лучшей читаемости нужно разделить её на 5 подстрок и склеить их «оператором +» (конкатенация строк) в таком виде:
- первая строка: «Всегда пишите код так, «
- вторая строка: «будто сопровождать его будет «
- третья строка: «склонный к насилию психопат, «
- четвертая строка: «который знает, где вы живете. «
- пятая строка: «Martin Golding»
Требования:
Изменить поле text согласно условию.
Solution.java
- Solution.java
package com.javarush.task.pro.task09.task0903; /* Строковые литералы */ public class Solution < public String string = "Всегда пишите код так," +"будто сопровождать его будет" +"склонный к насилию психопат," +"который знает,где вы живете." + "Martin Golding"; >
Комментарии (10)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Anonymous #1668285 Backend Developer
24 марта 2021, 19:12
Изменить поле text согласно условию, a у тебя поле называется string. валидатор не видит твой string)
Уровень 16
24 марта 2021, 16:53
Все дело в пробелах. Действительно нужны в конце всех, кроме последней, строк.
Уровень 19
7 января 2021, 14:12
Нужны пробелы в конце всех, кроме последней, строк. Перед знаком кавычек, нужен пробел.
Уровень 14
18 сентября 2020, 07:46
+»который знает,где вы живете.» — ты тут пробел пропустил «знает, где вы живете»
Aleksei Software Engineer в Cisco Expert
4 сентября 2020, 15:13
По правилам русского языка после запятой должен быть отступ.
Уровень 22
4 сентября 2020, 15:15
Что понимается под «отступом»? Пробел?
Aleksei Software Engineer в Cisco Expert
4 сентября 2020, 15:16
Aleksei Software Engineer в Cisco Expert
4 сентября 2020, 15:18
Попробуйте вывести ваш код в консоль и увидите, что после знаков препинания у вас нет пробелов, хотя должны быть.
Уровень 22
4 сентября 2020, 15:26
Уровень 16
5 сентября 2020, 14:23
У меня и без пробелов прошла. Попробуй просто заново сделать.
- Курсы программирования
- Регистрация
- Курс Java
- Помощь по задачам
- Цены
- Задачи-игры
Сообщество
JavaRush — это интерактивный онлайн-курс по изучению Java-программирования c нуля. Он содержит 1200 практических задач с проверкой решения в один клик, необходимый минимум теории по основам Java и мотивирующие фишки, которые помогут пройти курс до конца: игры, опросы, интересные проекты и статьи об эффективном обучении и карьере Java‑девелопера.