Каков САМЫЙ ЗЛОЙ код, который Вы когда-либо видели в производственной корпоративной среде? [закрытый]

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

 GRANT SELECT, INSERT, DELETE ON database TO username@'localhost' IDENTIFIED BY 'password';

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

FLUSH PRIVILEGES; 

Дополнительная информация о flush .

To см. текущие привилегии для пользователя, вызывают следующий запрос.

select * from mysql.user where User='username';

Подробнее о GRANT .

76
задан 12 revs, 10 users 62% 25 September 2015 в 22:14
поделиться

35 ответов

Предупреждение: Длинное страшное сообщение вперед

я записал об одном приложении, я продолжил работать прежде здесь и здесь . Для помещения его просто моя компания наследовала 130 000 строк мусора из Индии. Приложение было записано в C#; это было приложение кассира, тот же вид кассиров программного обеспечения использование позади счетчика каждый раз, когда Вы переходите к банку. Приложение отказало 40-50 раз в день, и оно просто не могло быть пересмотрено в рабочий код. Моя компания должна была переписать целое приложение в течение 12 месяцев.

, Почему это приложение является злым? Поскольку вида исходного кода было достаточно для сведения нормального человека с ума и безумного нормального человека. Скрученная логика, используемая для записи этого приложения, возможно, была только вдохновлена кошмаром Lovecraftian. Уникальные функции этого приложения включали:

  • Из 130 000 строк кода, целое приложение содержало 5 классов (исключая файлы формы). Все они были общедоступными статическими классами. Один класс назвали Globals.cs, который содержал 1000-е и 1000-е, и 1000-е общедоступных статических переменных раньше содержали все состояние приложения. Те пять классов содержали 20 000 строк общего количества кода с остающимся кодом, встроенным в формы.

  • необходимо ли задаться вопросом, как программистам удавалось записать такое большое приложение без каких-либо классов? Что они использовали для представления их объектов данных? Оказывается, что программистам удалось перестроить половину понятий, которые все мы узнали об ООП просто путем объединения ArrayLists, HashTables и DataTables. Мы видели многое из этого:

    • ArrayLists хеш-таблиц
    • Хеш-таблицы со строковыми ключами и значениями DataRow
    • ArrayLists DataTables
    • DataRows, содержащего ArrayLists, который содержал HashTables
    • ArrayLists DataRows
    • ArrayLists ArrayLists
    • HashTables со строковыми ключами и значениями HashTable
    • ArrayLists ArrayLists HashTables
    • Любая комбинация ArrayLists, HashTables, DataTables, о котором можно думать.

    Имеют в виду, ни одна из структур данных выше не со строгим контролем типов, таким образом, необходимо бросить любой таинственный объект, что Вы выходите из списка к корректному типу. Удивительно, какой комплекс, структуры данных Rube Goldberg-like можно создать использование просто ArrayLists, HashTables и DataTables.

  • Для совместного использования примера того, как использовать объектную модель, детализированную выше рассмотрите Учетные записи: исходный программист создал seperate HashTable для каждого мыслимого свойства учетной записи: HashTable, названный hstAcctExists, hstAcctNeedsOverride, hstAcctFirstName. Ключи для всех тех хеш-таблиц были “|” разделенная строка. Мыслимые ключи включали “123456|DDA”, “24100|SVG”, “100|LNS”, и т.д.

  • , Так как состояние целого приложения было с готовностью доступно от глобальных переменных, программисты нашли ненужным передать параметры методам. Я сказал бы, что 90% методов взяли 0 параметров. Из некоторых, которые сделали, все параметры были переданы как строки для удобства, независимо от того, что представила строка.

  • Побочный эффект бесплатные функции не существовали. Каждый метод изменил 1 или более переменных в классе Globals. Не все побочные эффекты имели смысл; например, один из методов проверки формы имел таинственный побочный эффект вычисления, и короткие платежи по кредитам для любой учетной записи был сохранен Globals.lngAcctNum.

  • , Хотя было много форм, была одна форма для управления их всех: frmMain.cs, который содержал целых 20 000 строк кода. Что сделало frmMain, делают? Все. Это искало учетные записи, распечатанные получения, распределенные наличные деньги, это сделало все.

    Иногда другие формы должны были назвать методы на frmMain. Вместо того, чтобы учитывать тот код из формы в отдельный класс, почему не только вызывают код непосредственно:

    ((frmMain)this.MDIParent).UpdateStatusBar(hstValues);
    
  • Для поиска учетных записей программисты сделали что-то вроде этого:

    bool blnAccountExists =
        new frmAccounts().GetAccountInfo().blnAccountExists
    

    Настолько плохо, как это уже создает невидимую форму для выполнения бизнес-логики, как Вы думаете, форма знала который учетная запись искать? Легкий That’s: форма могла получить доступ к Globals.lngAcctNum и Globals.strAcctType. (Кто не любит Венгерской записи?)

  • Повторное использование кода было синонимом для ctrl-c, ctrl-v. Я нашел, что методы с 200 строками копируют/вставляют через 20 форм.

  • приложение имело причудливую модель потоков, что-то, что мне нравится называть моделью потока-и-таймера: каждая форма, которая породила поток, имела таймер на нем. Каждый поток, который был порожден, начал таймер, который имел задержку на 200 мс; однажды запущенный таймер, это проверило бы, чтобы видеть, установил ли поток некоторую волшебную булевскую переменную, то это прервало бы поток. Получающийся ThreadAbortException глотали.

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

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

  • Каждый метод в приложении содержал блок попытки/выгоды. Каждое исключение зарегистрировали и глотали.

  • то, Кто должен включить перечисления при включении строк, так же легко!

  • Некоторый гений выяснил, что можно сцепить несколько средств управления формой до того же обработчика событий. Как программист обрабатывал это?

    private void OperationButton_Click(object sender, EventArgs e)
    {
        Button btn = (Button)sender;
        if (blnModeIsAddMc)
        {
            AddMcOperationKeyPress(btn);
        }
        else
        {
            string strToBeAppendedLater = string.Empty;
            if (btn.Name != "btnBS")
            {
                UpdateText();
            }
            if (txtEdit.Text.Trim() != "Error")
            {
                SaveFormState();
            }
            switch (btn.Name)
            {
                case "btnC":
                    ResetValues();
                    break;
                case "btnCE":
                    txtEdit.Text = "0";
                    break;
                case "btnBS":
                    if (!blnStartedNew)
                    {
                        string EditText = txtEdit.Text.Substring(0, txtEdit.Text.Length - 1);
                        DisplayValue((EditText == string.Empty) ? "0" : EditText);
                    }
                    break;
                case "btnPercent":
                    blnAfterOp = true;
                    if (GetValueDecimal(txtEdit.Text, out decCurrValue))
                    {
                        AddToTape(GetValueString(decCurrValue), (string)btn.Text, true, false);
                        decCurrValue = decResultValue * decCurrValue / intFormatFactor;
                        DisplayValue(GetValueString(decCurrValue));
                        AddToTape(GetValueString(decCurrValue), string.Empty, true, false);
                        strToBeAppendedLater = GetValueString(decResultValue).PadLeft(20)
                                                    + strOpPressed.PadRight(3);
                        if (arrLstTapeHist.Count == 0)
                        {
                            arrLstTapeHist.Add(strToBeAppendedLater);
                        }
                        blnEqualOccurred = false;
                        blnStartedNew = true;
                    }
                    break;
                case "btnAdd":
                case "btnSubtract":
                case "btnMultiply":
                case "btnDivide":
                    blnAfterOp = true;
                    if (txtEdit.Text.Trim() == "Error")
                    {
                        btnC.PerformClick();
                        return;
                    }
                    if (blnNumPressed || blnEqualOccurred)
                    {
                        if (GetValueDecimal(txtEdit.Text, out decCurrValue))
                        {
                            if (Operation())
                            {
                                AddToTape(GetValueString(decCurrValue), (string)btn.Text, true, true);
                                DisplayValue(GetValueString(decResultValue));
                            }
                            else
                            {
                                AddToTape(GetValueString(decCurrValue), (string)btn.Text, true, true);
                                DisplayValue("Error");
                            }
                            strOpPressed = btn.Text;
                            blnEqualOccurred = false;
                            blnNumPressed = false;
                        }
                    }
                    else
                    {
                        strOpPressed = btn.Text;
                        AddToTape(GetValueString(0), (string)btn.Text, false, false);
                    }
                    if (txtEdit.Text.Trim() == "Error")
                    {
                        AddToTape("Error", string.Empty, true, true);
                        btnC.PerformClick();
                        txtEdit.Text = "Error";
                    }
                    break;
                case "btnEqual":
                    blnAfterOp = false;
                    if (strOpPressed != string.Empty || strPrevOp != string.Empty)
                    {
                        if (GetValueDecimal(txtEdit.Text, out decCurrValue))
                        {
                            if (OperationEqual())
                            {
                                DisplayValue(GetValueString(decResultValue));
                            }
                            else
                            {
                                DisplayValue("Error");
                            }
                            if (!blnEqualOccurred)
                            {
                                strPrevOp = strOpPressed;
                                decHistValue = decCurrValue;
                                blnNumPressed = false;
                                blnEqualOccurred = true;
                            }
                            strOpPressed = string.Empty;
                        }
                    }
                    break;
                case "btnSign":
                    GetValueDecimal(txtEdit.Text, out decCurrValue);
                    DisplayValue(GetValueString(-1 * decCurrValue));
                    break;
            }
        }
    }
    
  • тот же гений также обнаружил великолепный тернарный оператор. Вот некоторые примеры кода:

    frmTranHist.cs [line 812]:

    strDrCr = chkCredits.Checked && chkDebits.Checked ? string.Empty
                        : chkDebits.Checked ? "D"
                            : chkCredits.Checked ? "C"
                                : "N";
    

    frmTellTransHist.cs [line 961]:

    if (strDefaultVals == strNowVals && (dsTranHist == null ? true : dsTranHist.Tables.Count == 0 ? true : dsTranHist.Tables[0].Rows.Count == 0 ? true : false))
    

    frmMain.TellCash.cs [line 727]:

    if (Validations(parPostMode == "ADD" ? true : false))
    
  • Вот фрагмент кода, который демонстрирует типичное неправильное употребление StringBuilder. Отметьте, как программист concats строка в цикле, затем добавляет получившую строку к StringBuilder:

    private string CreateGridString()
    {
        string strTemp = string.Empty;
        StringBuilder strBuild = new StringBuilder();
        foreach (DataGridViewRow dgrRow in dgvAcctHist.Rows)
        {
            strTemp = ((DataRowView)dgrRow.DataBoundItem)["Hst_chknum"].ToString().PadLeft(8, ' ');
            strTemp += "  ";
            strTemp += Convert.ToDateTime(((DataRowView)dgrRow.DataBoundItem)["Hst_trandt"]).ToString("MM/dd/yyyy");
            strTemp += "  ";
            strTemp += ((DataRowView)dgrRow.DataBoundItem)["Hst_DrAmount"].ToString().PadLeft(15, ' ');
            strTemp += "  ";
            strTemp += ((DataRowView)dgrRow.DataBoundItem)["Hst_CrAmount"].ToString().PadLeft(15, ' ');
            strTemp += "  ";
            strTemp += ((DataRowView)dgrRow.DataBoundItem)["Hst_trancd"].ToString().PadLeft(4, ' ');
            strTemp += "  ";
            strTemp += GetDescriptionString(((DataRowView)dgrRow.DataBoundItem)["Hst_desc"].ToString(), 30, 62);
            strBuild.AppendLine(strTemp);
        }
        strCreateGridString = strBuild.ToString();
        return strCreateGridString;//strBuild.ToString();
    }
    
  • Никакие первичные ключи, индексы или ограничения внешнего ключа не существовали на таблицах, почти все поля имели тип varchar (50), и 100% полей были nullable. Интересно, битовые поля не использовались, чтобы хранить булевы данные; вместо этого символ (1) поле использовалось, и символы 'Y' и 'N' раньше представляли истину и ложь соответственно.

    • Разговор о базе данных, вот представительный пример хранимой процедуры:

      ALTER PROCEDURE [dbo].[Get_TransHist]
       ( 
            @TellerID   int = null,
            @CashDrawer int = null,
            @AcctNum    bigint = null,
            @StartDate  datetime = null,
            @EndDate    datetime = null,
            @StartTranAmt     decimal(18,2) = null,
            @EndTranAmt decimal(18,2) = null,
            @TranCode   int = null,
            @TranType   int = null
       )
      AS 
            declare @WhereCond Varchar(1000)
            declare @strQuery Varchar(2000)
            Set @WhereCond = ' '
            Set @strQuery = ' '
            If not @TellerID is null
                  Set @WhereCond = @WhereCond + ' AND TT.TellerID = ' + Cast(@TellerID as varchar)
            If not @CashDrawer is null
                  Set @WhereCond = @WhereCond + ' AND TT.CDId = ' + Cast(@CashDrawer as varchar)
            If not @AcctNum is null
                  Set @WhereCond = @WhereCond + ' AND TT.AcctNbr = ' + Cast(@AcctNum as varchar)
            If not @StartDate is null
                  Set @WhereCond = @WhereCond + ' AND Convert(varchar,TT.PostDate,121) >= ''' + Convert(varchar,@StartDate,121) + ''''
            If not @EndDate is null
                  Set @WhereCond = @WhereCond + ' AND Convert(varchar,TT.PostDate,121) <= ''' + Convert(varchar,@EndDate,121) + ''''
            If not @TranCode is null
                  Set @WhereCond = @WhereCond + ' AND TT.TranCode = ' + Cast(@TranCode as varchar)
            If not @EndTranAmt is null
                  Set @WhereCond = @WhereCond + ' AND TT.TranAmt <= ' + Cast(@EndTranAmt as varchar)
            If not @StartTranAmt is null
                  Set @WhereCond = @WhereCond + ' AND TT.TranAmt >= ' + Cast(@StartTranAmt  as varchar)
            If not (@TranType is null or @TranType = -1)
                  Set @WhereCond = @WhereCond + ' AND TT.DocType = ' + Cast(@TranType as varchar)
            --Get the Teller Transaction Records according to the filters
            Set @strQuery = 'SELECT 
                  TT.TranAmt as [Transaction Amount], 
                  TT.TranCode as [Transaction Code],
                  RTrim(LTrim(TT.TranDesc)) as [Transaction Description],
                  TT.AcctNbr as [Account Number],
                  TT.TranID as [Transaction Number],
                  Convert(varchar,TT.ActivityDateTime,101) as [Activity Date],
                  Convert(varchar,TT.EffDate,101) as [Effective Date],
                  Convert(varchar,TT.PostDate,101) as [Post Date],
                  Convert(varchar,TT.ActivityDateTime,108) as [Time],
                  TT.BatchID,
                  TT.ItemID,
                  isnull(TT.DocumentID, 0) as DocumentID,
                  TT.TellerName,
                  TT.CDId,
                  TT.ChkNbr,
                  RTrim(LTrim(DT.DocTypeDescr)) as DocTypeDescr,
                  (CASE WHEN TT.TranMode = ''F'' THEN ''Offline'' ELSE ''Online'' END) TranMode,
                  DispensedYN
            FROM TellerTrans TT WITH (NOLOCK)
            LEFT OUTER JOIN DocumentTypes DT WITH (NOLOCK) on DocType = DocumentType
            WHERE IsNull(TT.DeletedYN, 0) = 0 ' + @WhereCond + ' Order By BatchId, TranID, ItemID'    
            Exec (@strQuery)
      

Со всем, что сказало, единственная самая большая проблема с этими 130 000 приложений строки это: никакие модульные тесты.

Да, я отправил эту историю TheDailyWTF, и затем я ушел c работы.

331
ответ дан 6 revs, 4 users 85% 24 November 2019 в 11:02
поделиться

Подобный тому, что кто-то еще упомянул выше:

я работал в месте, которое имело псевдоязык сценариев в приложении. Это питалось в крупный метод, который имел приблизительно 30 параметров и гиганта Select Case оператор.

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

Его решение?

Он добавил сингл object параметр на конце, таким образом, он мог передать в чем-либо, что он хотел и затем бросал его.

я не мог выйти из того места достаточно быстро.

2
ответ дан Ryan Lundy 24 November 2019 в 11:02
поделиться

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

, Это было Escape чуда..

И с тех пор, мы имеем автоматизированную сборку и развертываем процесс, к счастью:-)

2
ответ дан 2 revs, 2 users 89% 24 November 2019 в 11:02
поделиться

Я думаю, что это была программа, которая загрузила цикл в регистры общего назначения pdp-10 и затем выполнила код в тех регистрах.

Вы могли сделать это на pdp-10. Это не означает, что Вы должны.

РЕДАКТИРОВАНИЕ: по крайней мере, это в меру моего (иногда довольно потерто) воспоминание.

2
ответ дан leed25d 24 November 2019 в 11:02
поделиться

Я не забываю иметь необходимость установить IIS 3 для выполнения сценариев CGI Perl (да, который был looong время назад). Официальная рекомендация в то время состояла в том, чтобы поместить Perl.exe в cgi-мусорное-ведро. Это работало, но это также дало все доступ к довольно мощному механизму выполнения сценариев!

6
ответ дан Brian Rasmussen 24 November 2019 в 11:02
поделиться

Моему коллеге нравится вспоминать, что приложение ASP.NET, которое использовало public static соединение с базой данных для всей работы базы данных.

Да, одно соединение для всех запросов. И не, не было никакой блокировки, сделанной также.

8
ответ дан David Schmitt 24 November 2019 в 11:02
поделиться

Я видел, что шифрование пароля функционирует как это

function EncryptPassword($password)
{
    return base64_encode($password);
}
70
ответ дан 2 revs, 2 users 69% 24 November 2019 в 11:02
поделиться

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

Оказывается, что это недопустимо, который является нелеп данный нас, писали программу для Министерства юстиции в то время.

69
ответ дан Cameron MacFarland 24 November 2019 в 11:02
поделиться

Комбинация всех следующих Php 'Функции' сразу.

  1. Переменные Переменной Globals
  2. Регистра
  3. Включение удаленных файлов и кода через включает ("http://...");
  4. Действительно Ужасающий Массив/Имена переменной (Литеральный пример):

    foreach( $variablesarry as $variablearry ){
      include( $variablearry ); 
    }
    

    (я буквально провел час, пытаясь разработать, как это работало, прежде чем я понял их wern't та же переменная)

  5. Включают 50 файлов, которые каждый включает 50 файлов, и материал выполняется линейно/процедурно через все 50 файлов условными и непредсказуемыми способами.

Для тех, кто не знает переменные переменные:

$x = "hello"; 
$x = "world"; 
print $hello # "world" ;

Теперь полагают, что $x содержит значение от Вашего URL (зарегистрируйте globals волшебство), так нигде в Вашем коде не он очевидный что переменная Ваша работа с becuase все определенные URL.

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

$http://google.com,

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

Кроме того, когда его возможное для пользователя для определения переменной на URL, который указывает, какой файл включать, существуют противные приемы как [1 120]

http://foo.bar.com/baz.php?include=http://evil.org/evilcode.php

и если та переменная поднимается в include($include)

и 'evilcode.php', печатает его простой текст кода, и Php неуместно защищается, php будет просто катить прочь, загрузить evilcode.php и выполнить его как пользователя веб-сервера.

сеть - разъединяет, даст всему этому ее полномочия и т.д., разрешая вызовы оболочки, загружая произвольные двоичные файлы и выполняя их, и т.д. и т.д., пока в конечном счете Вы не задаетесь вопросом, почему у Вас есть поле, исчерпывающее дисковое пространство, и один dir имеет 8 ГБ пиратских фильмов с итальянским дублированием, совместно используемым на IRC с помощью бота.

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

(я мог развлекать dailywtf каждый день в течение 6 месяцев с той кодовой базой, я разыгрываю Вас нет. Его просто позор я обнаружил dailywtf после того, как я вышел из того кода)

28
ответ дан 3 revs 24 November 2019 в 11:02
поделиться

Установщик Windows.

25
ответ дан Charlie Martin 24 November 2019 в 11:02
поделиться

Я не знаю, назвал ли я код "злом", но у нас был разработчик, который создал бы Object[] массивы вместо того, чтобы писать классы. Везде.

19
ответ дан Willie Wheeler 24 November 2019 в 11:02
поделиться

Я не знаю, является ли это "злым" так, как дезинформировано (я недавно отправил его на Старой Новой Вещи):

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

16
ответ дан greg 24 November 2019 в 11:02
поделиться

Я не забываю видеть обработчик входов в систему, который взял запрос сообщения и перенаправил к ПОЛУЧЕНИЮ с именем пользователя и паролем, переданным в как параметры. Это было для "класса предприятия" медицинской системой.

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

14
ответ дан chris 24 November 2019 в 11:02
поделиться

Действительно злой была эта часть блестящего кода Дельфи:

type
  TMyClass = class
  private
    FField : Integer;
  public
    procedure DoSomething;
  end;

var
  myclass : TMyClass;


procedure TMyClass.DoSomething;
begin
  myclass.FField := xxx; // 
end;

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

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

12
ответ дан Toon Krijthe 24 November 2019 в 11:02
поделиться

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

18
ответ дан Sergey 24 November 2019 в 11:02
поделиться

Кодировка Base 36 для хранения целых чисел в строках.

Я полагаю, что теория идет примерно так:

  • Шестнадцатеричная система используется для представления чисел
  • Шестнадцатеричная система не использует буквы за пределами F, что означает, что GZ потрачены впустую
  • Отходы плохие

В данный момент я работаю с базой данных, в которой хранятся дни недели, в которые событие может произойти, в виде 7-битного битового поля (0-127) хранится в базе данных в виде двухсимвольной строки в диапазоне от «0» до «3J».

15
ответ дан 24 November 2019 в 11:02
поделиться

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

Имейте в виду, что это в .NET. где службы очень легко создавать.

-

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

-

На последнем месте, где я работал, у одного из архитекторов был сингл Файл исходного кода C # с более чем 100 классами размером около 250 КБ.

4
ответ дан 24 November 2019 в 11:02
поделиться

Любая RFC 3514 -совместимая программа, которая устанавливает злой бит .

5
ответ дан 24 November 2019 в 11:02
поделиться

Это была процедура обработки ошибок в части коммерческий код:

/* FIXME! */
while (TRUE)
    ;

Я должен был выяснить, почему «приложение блокируется».

30
ответ дан 24 November 2019 в 11:02
поделиться

Я видел код на сайте ASP.NET MVC от парня, который до этого делал только веб-формы (и является известным копированием / пастером!), Который застревает событие щелчка на стороне клиента на тег , который вызывает метод javascript, который выполняет document.location.

Я пытался объяснить, что href в теге будет сделай то же самое !!!

11
ответ дан 24 November 2019 в 11:02
поделиться

32 Файлы исходных кодов с более чем 10К строки кода каждый. Каждый содержит один класс. Каждый класс содержал один метод, который сделал «все»

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

3
ответ дан 24 November 2019 в 11:02
поделиться

У нас было приложение, которое загружало все свое глобальное состояние в файл xml. С этим нет проблем, за исключением того, что разработчик создал новую форму рекурсии.

<settings>
  <property>
      <name>...</name>
      <value>...</value>
      <property>
          <name>...</name>
          <value>...</value>
          <property>
              <name>...</name>
              <value>...</value>
              <property>
                   <name>...</name>
                   <value>...</value>
                   <property>
                        <name>...</name>
                        <value>...</value>
                       <property>
                             <name>...</name>
                             <value>...</value>
                            <property>

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

List properties = new List();
Node<-root
while node.hasNode("property")
    add to properties list
    my_global_variable++;
    if hasNode("property")
         node=getNode("property"), ... etc etc

И затем вы получаете функции вроде

calculateSumOfCombinations(int x, int y){
   return x+y+my_global_variable;
}

edit: пояснение - Мне потребовалось много времени, чтобы понять, что он подсчитывал глубину рекурсии, потому что на уровне 6 или 7 свойства изменили значение, поэтому он использовал счетчик, чтобы разделить свой набор квартир на 2 набора разных типов, вроде того, что у него был список СОСТОЯНИЕ, СОСТОЯНИЕ, СОСТОЯНИЕ, ГОРОД, ГОРОД, ГОРОД и проверял, есть ли index> counter, чтобы узнать, название вашего города или штата)

5
ответ дан 24 November 2019 в 11:02
поделиться

На более раннем рабочем месте мы унаследовали устаревший проект, который ранее частично был передан на аутсорсинг. Основным приложением была Java, а аутсорсинговой частью - нативная библиотека C. Однажды я взглянул на исходные файлы C. Я перечислил содержимое каталога. Было несколько исходных файлов размером более 200 КБ. Самый большой файл C был 600 Кбайт .

Слава Богу, мне никогда не приходилось их трогать: -)

3
ответ дан 24 November 2019 в 11:02
поделиться

В главном файле заголовка проекта от старого программиста на COBOL, который необъяснимо писал компилятор на C:

int i, j, k;

«Итак, вы выиграли» t получить ошибку компилятора, если вы забудете объявить переменные цикла. "

28
ответ дан 24 November 2019 в 11:02
поделиться

Может быть, не зло, но, конечно, довольно, гм... заблуждение.

Однажды мне пришлось переписывать "парсер естественного языка", который был реализован в виде одного оператора if...then, состоящего из 5000 строк.

как в...

if (text == "hello" || text == "hi")
    response = "hello";
else if (text == "goodbye")
    response = "bye";
else
    ...
12
ответ дан 24 November 2019 в 11:02
поделиться

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


Новые способы использования имен для детей

Купите книгу по именованию детей, и вы никогда не потеряете имена переменных. Фред - прекрасное имя, и его легко набрать. Если вы ищете простые для ввода имена переменных, попробуйте adsf или aoeu, если вы печатаете с клавиатуры DSK.

Креативные орфографические ошибки

Если вы должны использовать описательные имена переменных и функций, сделайте их неправильное написание. Опечатка в некоторых именах функций и переменных и правильное написание в других (например, SetPintleOpening SetPintalClosing) фактически сводит на нет использование методов поиска grep или IDE. Работает на удивление хорошо. Добавьте интернациональный колорит, произнося тори или тори в разных театрах / театрах.

Будьте абстрактными

При именовании функций и переменных интенсивно используйте такие абстрактные слова, как это, все, данные, дескриптор, прочее, делать, процедура, выполнение и цифры, например. подпрограммыX48, PerformDataFunction, DoIt, HandleStuff и do_args_method.

заглавные буквы

В случайном порядке использовать заглавную первую букву слога в середине слова. Например ComputeRasterHistoGram ().

Нижний регистр l во многом похож на цифру 1.

Используйте нижний регистр l для обозначения длинных констант. например 10l с большей вероятностью будет ошибочно принято за 101, чем 10L. Запретите любые шрифты, которые явно устраняют неоднозначность uvw wW gq9 2z 5s il17 |! J oO08 `'";,. M nn rn {[()]}. Будьте изобретательны.

Переработайте свои переменные

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

Cd wrttn wtht vwls s mch trsr

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

Непонятные ссылки на фильмы

Используйте имена констант, такие как LancelotsFavouriteColour вместо синего, и присвойте ему шестнадцатеричное значение $ 0204FB. Цвет на экране выглядит идентично синему цвету, и программисту по обслуживанию придется проработать 0204FB (или использовать какой-либо графический инструмент), чтобы узнать, как он выглядит.Только тот, кто хорошо знаком с Монти Пайтоном и Святым Граалем, мог знать, что любимым цветом Ланселота был синий. Если программист по обслуживанию не может цитировать по памяти целые фильмы Монти Пайтона, ему нечего делать программистом.

Задокументируйте очевидное.

Добавьте в код комментарии вроде / * добавить 1 к i * /, однако никогда не документируйте непонятные вещи, такие как общая цель пакета или метода.

Документируйте, как не почему

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

Побочные эффекты

В C функции должны быть идемпотентными (без побочных эффектов). Надеюсь, этой подсказки достаточно.

Используйте Octal

Вставьте восьмеричные литералы в список десятичных чисел, например:

array = new int []
{ 
111, 
120, 
013, 
121, 
};

Расширенный ASCII

Расширенные символы ASCII вполне допустимы в качестве имен переменных, включая символы ß, Ð и ñ. Их практически невозможно набрать без копирования / вставки в простом текстовом редакторе.

Имена из других языков

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

Имена из математики

Выберите имена переменных, которые маскируются под математические операторы, например:

openParen = (slash + asterix) / equals;

Код, маскирующийся под комментарии и наоборот

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

for(j=0; j<array_len; j+ =8)
{ 
total += array[j+0 ]; 
total += array[j+1 ]; 
total += array[j+2 ]; /* Main body of 
total += array[j+3];   * loop is unrolled 
total += array[j+4];   * for greater speed. 
total += array[j+5];   */ 
total += array[j+6 ]; 
total += array[j+7 ]; 
}

Без цветовой кодировки вы бы заметили, что три строки кода закомментированы?

Произвольные имена, маскирующиеся под ключевые слова

При документировании, и вам нужно произвольное имя для представления имени файла, используйте «файл».Никогда не используйте явно произвольное имя, например «Charlie.dat» или «Frodo.txt». Как правило, в ваших примерах используйте произвольные имена, которые максимально похожи на зарезервированные ключевые слова. Например, хорошими именами для параметров или переменных могут быть «банк», «пустой», «класс», «константа», «константа», «вход», «ключ», «ключевое слово», «вид», «выход». , «параметр», «параметр», «система», «тип», «значение», «переменная» и «переменная». Если вы используете фактические зарезервированные слова для своих произвольных имен, которые будут отклонены вашим командным процессором или компилятором, тем лучше. Если вы сделаете это хорошо, пользователи будут безнадежно запутаны между зарезервированными ключевыми словами и произвольными именами в вашем примере, но вы можете выглядеть невиновным, утверждая, что вы сделали это, чтобы помочь им связать соответствующую цель с каждой переменной.

Имена кодов не должны совпадать с экранными именами

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

Выбор лучшего оператора перегрузки

В C ++ перегрузка +, -, *, / для выполнения действий, совершенно не связанных с сложением, вычитанием и т. Д. В конце концов, если Stroustroup может использовать оператор сдвига для выполнения операций ввода-вывода, почему бы вам не быть столь же креативным? Если вы перегружаете +, убедитесь, что вы делаете это так, что i = i + 5; имеет совершенно иное значение, чем i + = 5; Вот пример поднятия обфускации оператора перегрузки до высокого уровня искусства. Перегрузите '!' оператор для класса, но перегрузка не имеет ничего общего с инвертированием или отрицанием. Сделайте так, чтобы он возвращал целое число.Затем, чтобы получить для него логическое значение, вы должны использовать '! ! '. Однако это меняет логику, поэтому [барабанная дробь] вы должны использовать '! ! ! '. Не путайте! оператор, который возвращает логическое значение 0 или 1, с оператором побитового логического отрицания ~.

Исключения

Я открою вам малоизвестный секрет кодирования. Исключения - это головная боль. Правильно написанный код никогда не дает сбоев, поэтому в исключениях нет необходимости. Не тратьте на них время. Исключения подкласса предназначены для некомпетентных людей, которые знают, что их код потерпит неудачу. Вы можете значительно упростить свою программу, имея только одну попытку / уловку во всем приложении (в основном), которое вызывает System.exit (). Просто прикрепите совершенно стандартный набор бросков к каждому заголовку метода, независимо от того, могут ли они действительно выдавать какие-либо исключения или нет.

Расположение магической матрицы

Используйте специальные значения в определенных местах матрицы в качестве флагов. Хорошим выбором является элемент [3] [0] в матрице преобразования, используемой с однородной системой координат.

Возвращение к Magic Array Slots

Если вам нужно несколько переменных определенного типа, просто определите их массив, а затем обращайтесь к ним по номеру. Выберите соглашение о нумерации, известное только вам, и не документируйте его. И не беспокойтесь об определении констант #define для индексов. Все должны просто знать, что виджет глобальной переменной [15] - это кнопка отмены. Это просто актуальный вариант использования абсолютных числовых адресов в ассемблерном коде.

Никогда не украшайте

Никогда не используйте автоматические средства упорядочивания исходного кода (средства улучшения) для выравнивания кода.Лоббируйте, чтобы они забанили их из вашей компании на том основании, что они создают ложные дельты в PVCS / CVS (отслеживание контроля версий) или что у каждого программиста должен быть свой собственный стиль отступов, который навсегда останется неприкосновенным для любого написанного им модуля. Настаивайте, чтобы другие программисты соблюдали эти идиосинкразические соглашения в «его» модулях. Запретить украшения довольно просто, даже если они сэкономят миллионы нажатий клавиш на ручное выравнивание и потраченные впустую дни на неверную интерпретацию плохо выровненного кода. Просто настаивайте, чтобы все использовали один и тот же упорядоченный формат не только для хранения в общем репозитории, но и во время редактирования. Это запускает RWAR, и босс, чтобы сохранить мир, запретит автоматическую уборку. Без автоматической очистки теперь вы можете случайно неправильно выровнять код, чтобы создать оптическую иллюзию, что тела циклов и if длиннее или короче, чем они есть на самом деле, или что предложения else соответствуют другому if, чем они есть на самом деле. например

if(a)
  if(b) x=y;
else x=z;

Тестирование для трусов

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

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

Переверните обычное соглашение «истина-ложь»

Поменяйте местами обычные определения истинного и ложного. Звучит очень очевидно, но работает отлично. Вы можете спрятать:

#define TRUE 0 
#define FALSE 1

где-нибудь глубоко в коде, чтобы он был извлечен из недр программы из какого-то файла, на который никто больше не смотрит. Затем заставьте программу выполнять сравнения, например:

if ( var == TRUE )
if ( var != FALSE )

кто-то должен «исправить» очевидную избыточность и использовать var в другом месте обычным способом:

if ( var )

Другой способ - сделать так, чтобы TRUE и FALSE имели одно и то же значение, хотя большинство сочли бы это полным обманом. Использование значений 1 и 2 или -1 и 0 - более тонкий способ сбить людей с толку и при этом выглядеть респектабельно. Вы можете использовать тот же метод в Java, определив статическую константу с именем TRUE. Программисты могут быть более подозрительными, потому что в Java есть встроенный литерал true.

Exploit Schizophrenia

Java - шизофреник в отношении объявлений массивов. Вы можете использовать их как в старом C, способ String x [], (который использует смешанную пре-постфиксную нотацию), так и новый способ String [] x, который использует чистую префиксную нотацию. Если вы хотите по-настоящему запутать людей, смешайте обозначения, например, g.

byte[ ] rowvector, colvector , matrix[ ];

, что эквивалентно:

byte[ ] rowvector; 
byte[ ] colvector; 
byte[ ][] matrix;
20
ответ дан 24 November 2019 в 11:02
поделиться

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

Осознав это, я провел текстовое сравнение всех копий. Из 16, я думаю, было около 9 уникальных. У меня начался приступ.

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

Непечатаемые символы использовались для передачи данных (все строки!) от сервера к клиенту. Поэтому все строки были разделены символом 0x03 на стороне сервера и повторно собраны на стороне клиента в C# с помощью функции Split.

Вполне разумным способом было бы сделать:

someVariable.Split(Convert.ToChar(0x03);

Более разумным и дружественным способом было бы использовать константу:

private const char StringSeparator = (char)0x03;
//...
someVariable.Split(StringSeparator);

ЗЛОЙ способ - это то, что выбрали мои коллеги: использовать все, что "печатается" для 0x03 в Visual Studio и поместить это между кавычками:

someVariable.Split('/*unprintable character*/');

Более того, в этой библиотеке (и всех связанных программах) ни одна переменная не была локальной (я проверял!). Функции были предназначены либо для восстановления одних и тех же переменных после того, как их сочтут безопасными, либо для создания новых, которые будут жить на протяжении всего процесса. Я распечатал несколько страниц и обозначил их цветом. Желтый цвет означал "глобальная, никогда не изменяемая другой функцией", красный - "глобальная, изменяемая несколькими". Зеленый цвет означал "локальный", но его не было.

О, я упоминал о контроле версий? Потому что, конечно, его не было.

ДОПОЛНЕНИЕ: Я только что вспомнил об одной функции, которую я обнаружил не так давно.

Ее целью было пройти через массив массивов интергеров, и установить каждый первый и последний элемент в 0. Это выглядело так (не реальный код, по памяти, и больше похоже на C#):

FixAllArrays()
{
    for (int idx = 0; idx < arrays.count- 1; idx++)
    {
        currArray = arrays[idx];
        nextArray = arrays[idx+1];
        SetFirstToZero(currArray);
        SetLastToZero(nextArray);

        //This is where the fun starts
        if (idx == 0)
        {
            SetLastToZero(currArray);
        }

        if (idx == arrays.count- 1)
        {
            SetFirstToZero(nextArray);
        }
    }
}

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

3
ответ дан 24 November 2019 в 11:02
поделиться

SQL-запросы прямо в javascript в приложении ASP. Грязнее не бывает ...

5
ответ дан 24 November 2019 в 11:02
поделиться

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

Он написал статью, когда до него дошли слухи об увольнениях, и если он упадет, компании придется пострадать.

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

Конечно ... через несколько месяцев нас всех уволили.

10
ответ дан 24 November 2019 в 11:02
поделиться

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

Основные биты ничем не примечательны. Red Hat Enterprise Linux, MySQL, DRBD и Linux-HA. Конфигурация, однако, поддерживалась полностью настраиваемой марионеточной системой (неудивительно, что есть много других примеров безумия в результате этой системы).

Оказывается, система проверяла файл install.log , который Kickstart оставляет в корневом каталоге, на предмет части информации, необходимой для создания конфигурации DRBD. Само по себе это, конечно, зло. Вы не извлекаете конфигурацию из файла журнала, формат которого фактически не определен. Однако становится еще хуже.

Он не хранил эти данные где-либо еще, и каждый раз при запуске, то есть каждые 60 секунд, он обращался к install.log .

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

2
ответ дан 24 November 2019 в 11:02
поделиться
Другие вопросы по тегам:

Похожие вопросы: