Какие пять вещей ты ненавидишь в своем любимом языке?

В последнее время на Stack Overflow была куча Perl-ненависти, поэтому я решил перенести вопрос " Пять вещей, которые ты ненавидишь за свой любимый язык" в Stack Overflow. Возьми свой любимый язык и скажи мне пять вещей, которые ты ненавидишь. Это могут быть вещи, которые вас раздражают, допущенные недостатки дизайна, признанные проблемы с производительностью или любая другая категория. Вы просто должны ненавидеть это, и это должен быть ваш любимый язык.

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

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

Мне все равно, какой язык вы используете. Не хотите использовать определенный язык? Тогда не надо. Вы проходите тщательную проверку, чтобы сделать осознанный выбор, и все еще не используете его? Хорошо. Иногда правильный ответ звучит так: "У вас сильная команда программистов с хорошими практиками и большим опытом работы в Bar. Переход на Foo был бы глупым".


Это хороший вопрос и для обзоров кода. Люди, которые действительно знают кодовую базу, будут иметь всевозможные предложения для этого, и те, кто не знает это так хорошо, имеют неконкретные жалобы. Я спрашиваю: "Если бы вы могли начать этот проект заново, что бы вы сделали по-другому?" На этой фэнтезийной земле пользователи и программисты могут жаловаться на все, что им не нравится."Мне нужен лучший интерфейс", "Я хочу отделить модель от представления", "Я бы использовал этот модуль вместо другого", "Я бы переименовал этот набор методов", или что бы они ни делали не нравится о текущей ситуации. That's how I get a handle on how much a particular developer knows about the codebase. It's also a clue about how much of the programmer's ego is tied up in what he's telling me.

Hate isn't the only dimension of figuring out how much people know, but I've found it to be a pretty good one. The things that they hate also give me a clue how well they are thinking about the subject.

182 ответа

Решение

Пять вещей, которые я ненавижу в Java:

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

Я знаю, я должен проверить Скала.

Вау, я удивлен, что SQL еще не дошел до этого. Думаю, это означает, что никто не любит это:)

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

... и несколько бонусов, чтобы ненавидеть это, без дополнительной оплаты

  • предложение WHERE идет последним, что облегчает преждевременное выполнение UPDATE или DELETE, уничтожая всю таблицу. Вместо этого ГДЕ должно идти куда-то впереди.
  • Трудно реализовать реляционное деление.
  • Я могу установить значение NULL, но я не могу проверить его на равенство с NULL. Я могу проверить IS NULL, но это только усложняет код - без необходимости, на мой взгляд.
  • Почему нам нужно полностью изменить формулу для столбца GROUPed, а не устанавливать псевдоним для столбца, а затем псевдоним GROUP BY (или индекс столбца, как при SORT)?

JavaScript:

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

  2. '+' - абсурдный выбор оператора для конкатенации в слабо типизированном языке. Они пытались отпугнуть новичков?

  3. Это минное поле совместимости с разными браузерами (неважно, включено оно или нет)

  4. Как правило, это ненадежно - связано с разборками, такими как блокировка кнопки "назад", всплывающие окна, которые никогда не умирают, и т. Д.

  5. Отладка практически невозможна, потому что есть только несколько разных сообщений об ошибках и несколько разных типов (Number, String, Object и т. Д.)

Если бы не JQuery, я бы все равно ненавидел его так же, как раньше:)

PHP:

1) Заставляет меня делать ненужные переменные:

$parts = explode('|', $string);
$first = $parts[0];

2) Реализация лямбд, так что хромать это примерно эквивалентно использованию eval() и так ужасно неправильно, я никогда не использовал его (см. http://www.php.net/create_function).

3) Система try/catch, которая может отлавливать только около 80% возможных ошибок.

4) Поддержка Regex такая же хромая, как и лямбда-поддержка, потому что она должна быть написана внутри обычных строк, что делает один из самых сложных в освоении инструментов программирования примерно в три раза сложнее. А PHP должен быть "легким" языком?!?!?

5) Нет способа безопасно извлечь что-либо из $_POST, не написав его дважды, не создав собственную функцию или не используя оператор '@':

$x = isset($_POST['foo']['bar']) ? $_POST['foo']['bar'] : null;

6) Бонусный ответ: "@". Если вы не можете быть обеспокоены написанием своего кода правильно, просто добавьте '@', и это слишком плохо для тех, кому позже придется отлаживать ваш код.

C++

  • Слишком легко случайным образом повредить память и создать почти невозможные для поиска ошибки (хотя Valgrind проделывает долгий путь к исправлению этой ошибки).
  • Шаблон сообщений об ошибках.
  • При использовании шаблонов легко в конечном итоге включить все в один файл, а затем получить глупые времена компиляции.
  • Стандартная библиотека - шутка в современную эпоху (по-прежнему нет потоков или сети по умолчанию?)
  • Множество неприятных маленьких кусочков C, проходящих через (в частности, все преобразования между short/int/unsigned/etc..)

C# / .NET:

  • Классы должны быть запечатаны по умолчанию
  • Там не должно быть lock утверждение - вместо этого у вас должны быть определенные блокирующие объекты, и должны быть такие методы, как Acquire которые возвращают одноразовые жетоны замка. Следствие: не должно быть монитора для каждого объекта.
  • GetHashCode() а также Equals() не должно быть в System.Object - не все подходит для хеширования. Вместо этого есть IdentityComparer который делает то же самое, и сохранить IComparer<T>, IComparable<T>, IEqualityComparer<T> а также IEquatable<T> интерфейсы для пользовательских сравнений.
  • Слабая поддержка неизменности
  • Плохой способ обнаружения методов расширения - это должно быть гораздо более осознанным решением, чем просто тот факт, что я использую пространство имен.

Это было не в моей голове - спросите меня завтра, и я приду к другому 5:)

С

  • манипуляции со струнами.

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

Как насчет пяти вещей, которые я ненавижу в списках "Вещи, которые я ненавижу в каком-то языке"?: D

5 - Оранжевый красный не делает его яблоком.

Когда проектируется язык, дизайнеры обычно имеют в виду, для чего он нужен. Использование этого для чего-то совершенно другого может работать, но жаловаться, когда это не так, просто глупо. Возьми Питона. Я уверен, что или кто-то имеет, или кто-то когда-нибудь сделает утилиту для создания exe-файлов из кода Python. Почему на земле Бога вы хотите это сделать? Это было бы здорово - не поймите меня неправильно - но это бесполезно. Так что перестаньте жаловаться на это!

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

4- Вы стоите на деревянных ногах?

Платформа может оказать большое влияние на то, что может сделать язык. В настоящее время сборщики мусора, или даже ранняя попытка "сбора мусора" в паскалях, могут помочь в исчезновении памяти (может быть, malloc больше оперативной памяти??). Компьютеры работают быстрее и, конечно, мы ожидаем большего от наших языков. И, честно говоря, мы, вероятно, должны. Однако за удобство компилятора приходится платить огромную цену за создание хеш-таблиц или строк, а также за множество других концепций. Эти вещи не могут наследоваться той платформе, на которой они используются. Сказать, что их легко включить в язык, просто говорит мне, что у вас может не быть ноги, на которой можно стоять.

3- Кто виноват, это правда?

Ошибок. Ты знаешь. Я люблю жуков. Почему я люблю жуков. Потому что это значит, что я могу сохранить свою работу. Без ошибок было бы много закрытых пиццерий. Тем не менее, пользователи ненавидят ошибки. Но вот небольшой всплеск холодной воды. Каждая ошибка - ошибка программистов. Не язык. Язык с таким строгим синтаксисом, который значительно уменьшил бы количество возможных ошибок, был бы совершенно бесполезным языком. Его способности, вероятно, можно посчитать с одной стороны. Вы хотите гибкости или власти? У вас есть ошибки. Зачем? Потому что ты не идеален, и ты совершаешь ошибки. Возьмите действительно идентифицируемый пример в C:

int a[10];
for (int idx = 0; idx < 15; idx++) a[idx] = 10;

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

2- Shouldn't we put that in the recycle bin?

It's very easy to point at a feature in a language we don't understand because we don't use it often and call it stupid. Complain that it's there etc. Goto's always entertain me. People always complain about goto's being in a language. Yet I bet your last program included a type of goto. If you have ever used a break or a continue, you've used a goto. Это и есть. Granted, it's a "safe" goto, but it is what it is. Goto's have their uses. Whether "implicit" gotos like continue or break are used or explicit gotos (using the actual keyword "goto" for whatever language). Not that language developers are flawless, but typically... if functionality has existed since the dawn of time (for that language). Likely that aspect is a defining quality of that language. Meaning.. it's being used and likely is not hanging around because of backwards compatibility. It's being used today. As in 5 minutes ago. And used properly. Well.. arguably someone is using it improperly as well, but that relates to #3 on my list.

1. - Everything is an object.

Ok.. this one is really a subset oF#2. But this is by far the most annoying complaint I see in hate lists. Not everything is an object. There are a great many of concepts that do not belong or need to be objects. Putting things where they don't belong is just ugly and can decrease efficiency of a program. Конечно. Maybe not much depending on the language. This also relates to #5. This means... yes. Global are ok. Functions as apposed to static methods are ok. Combining OO programming with global functions is ok. Now.. that doesn't mean we should all go out and "free" our code from it's object models either. When designing a section of code or a whole project, what happens behind the scenes should be considered when putting it together. Not only where that concept lives and many other factors. Why wrap global functions within classes or name space concepts if it serves no purpose? Take static member variables. That greatly amuses me because.. well..Depending on the language and implementation of course, but generally speaking, you just declared a global. Yes, there are some reasons to wrap these non-OO concepts in OO wrappers. One of course being self documenting code. That can make sense. So.. like I say. Don't go out and "free" your code. But any good modern language will have a global concept outside of it's OO modeling. Yes I'm specifically meaning to point out that an OO programming language without a global concept most likely has a serious design flaw. Again though.. depends on the intention and design of the language so I'm not attempting to pick on any specific language and there are far too many to analyze right here. Anywho, Consider where the code should live and be the most effective. Adding a bunch of flare to something which doesn't add functionality or support just wears down the keyboard faster. It doesn't do anybody any good. Well.. unless you like brownie points from the person who probably incorrectly taught you that everything is an object.

In short, programming isn't just mindlessly tapping on the keyboard. There are a lot of design considerations to any project. I know it's cliche, but you have to look at it from every angle. Even with nowadays type-safe languages. You don't just chuck code out and expect it to work well. Sure.. it may work, but it may not be the right way to go about it. Overall, pick the language and format that is best suited for the specific job AND the environment. But no language takes away the thought behind it. If you're not thinking.. you're just typing.

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

  1. Несмотря на то, что я фанат Java Generics, есть много странностей, которые возникают из-за того, как он был спроектирован. Таким образом, существует множество раздражающих ограничений с помощью дженериков (некоторые из которых являются результатом стирания типа).
  2. Принцип работы Object.clone() и интерфейсов Cloneable полностью нарушен.
  3. Вместо того, чтобы идти по шоссе и делать все объектами (например, SmallTalk), Sun освободилась от создания двух разных категорий типов данных: объекты и примитивы. В результате теперь есть два представления для основных типов данных и странных курьезов, таких как бокс / распаковка и невозможность поместить примитивы в коллекцию.
  4. Качели слишком сложны. Не поймите меня неправильно: с Swing можно сделать много интересных вещей, но это отличный пример чрезмерного проектирования.
  5. Эта последняя жалоба в равной степени является ошибкой Sun и тех, кто написал XML-библиотеки для Java. Библиотеки Java XML слишком сложны. Чтобы просто читать в XML-файле, мне часто приходится беспокоиться о том, какой анализатор я использую: DOM или SAX? API для каждого одинаково сбивает с толку. Нативная поддержка языка для простого разбора / написания XML была бы очень хорошей.
  6. дата отстой. Это не только излишне сложно, но и все полезные методы устарели (и заменены другими, которые увеличивают сложность).

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

  • Замыкания (блоки) имеют 4 различных синтаксиса создания, и ни один из них не является оптимальным. Элегантный синтаксис неполон и неоднозначен с хешами, а полный синтаксис уродлив.
  • Сообщество имеет тенденцию выступать против реальной документации, предпочитая "читать код". Я нахожу это по-детски и ленивым.
  • Злоупотребление метапрограммированием, особенно в библиотеках, превращает ошибки в кошмар.
  • Относительно примечания: повсеместное метапрограммирование делает сложную, если не невозможную, комплексную среду разработки.
  • Способ передачи блока в функции глупый. Нет причин, по которым блоки должны передаваться за пределы списка параметров или иметь странный специальный синтаксис для доступа (yield). Я придерживаюсь мнения, что блокам должен был быть задан менее неоднозначный синтаксис (или хэши могли бы использовать разные разделители; возможно, <>, а не {}), и передача в качестве параметров в методы должна была быть такой же, как и все остальные параметры.

    object.method(1, {|a| a.bar}, "blah")
    

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

Perl

  • Смешанное использование сигил

    my @array = ( 1, 2, 3 );
    my $array = [ 4, 5, 6 ];
    
    my $one  = $array[0]; # not @array[0], you would get the length instead
    my $four = $array->[0]; # definitely not $array[0]
    
    my( $two,  $three ) = @array[1,2];
    my( $five, $six   ) = @$array[1,2]; # coerce to array first
    
    my $length_a = @array;
    my $length_s = @$array;
    
    my $ref_a = \@array;
    my $ref_s = $array;
    
    • Например, ни один из них не одинаков:

      $array[0]   # First element of @array
      @array[0]   # Slice of only the First element of @array
      %array[0]   # Syntax error
      $array->[0] # First element of an array referenced by $array
      @array->[0] # Deprecated first element of @array
      %array->[0] # Invalid reference
      $array{0}   # Element of %array referenced by string '0'
      @array{0}   # Slice of only one element of %array referenced by string '0'
      %array{0}   # Syntax error
      $array->{0} # Element of a hash referenced by $array
      @array->{0} # Invalid reference
      %array->{0} # Deprecated Element of %array referenced by string '0'
      

    В Perl6 написано:

    my @array = ( 1, 2, 3 );
    my $array = [ 4, 5, 6 ];
    
    my $one  = @array[0];
    my $four = $array[0]; # $array.[0]
    
    my( $two,  $three ) = @array[1,2];
    my( $five, $six   ) = $array[1,2];
    
    my $length_a = @array.length;
    my $length_s = $array.length;
    
    my $ref_a = @array;
    my $ref_s = $array;
    
  • Отсутствие истинного OO

    package my_object;
    # fake constructor
    sub new{ bless {}, $_[0] }
    # fake properties/attributes
    sub var_a{
      my $self = shift @_;
      $self->{'var_a'} = $_[0] if @_;
      $self->{'var_a'}
    }
    

    В Perl6 написано:

    class Dog is Mammal {
        has $.name = "fido";
        has $.tail is rw;
        has @.legs;
        has $!brain;
        method doit ($a, $b, $c) { ... }
        ...
    }
    
  • Плохо разработанные функции регулярных выражений

    /(?=regexp)/;           # look ahead
    /(?<=fixed-regexp)/;    # look behind
    /(?!regexp)/;           # negative look ahead
    /(?<!fixed-regexp)/;    # negative look behind
    /(?>regexp)/;           # independent sub expression
    /(capture)/;            # simple capture
    /(?:don't capture)/;    # non-capturing group
    /(?<name>regexp)/;      # named capture
    /[A-Z]/;                # character class
    /[^A-Z]/;               # inverted character class
    # '-' would have to be the first or last element in
    # the character class to include it in the match
    # without escaping it
    /(?(condition)yes-regexp)/;
    /(?(condition)yes-regexp|no-regexp)/;
    /\b\s*\b/;              # almost matches Perl6's <ws>
    /(?{ print "hi\n" })/;  # run perl code
    

    В Perl6 написано:

    / <?before pattern>  /;   # lookahead
    / <?after pattern>   /;   # lookbehind
    / regexp :: pattern  /;   # backtracking control
    / ( capture )        /;   # simple capture
    / $<name>=[ regexp ] /;   # named capture
    / [ don't capture ]  /;   # non-capturing group
    / <[A..Z]>           /;   # character class
    / <-[A..Z]>          /;   # inverted character class
    # you don't generally use '.' in a character class anyway
    / <ws>               /;   # Smart whitespace match
    / { say 'hi' }       /;   # run perl code
    
  • Отсутствие многократной отправки

    sub f(   int $i ){ ... }  # err
    sub f( float $i ){ ... }  # err
    sub f($){ ... } # occasionally useful
    

    В Perl6 написано:

    multi sub f( int $i ){ ... }
    multi sub f( num $i ){ ... }
    multi sub f( $i where $i == 0 ){ ... }
    multi sub f(     $i ){ ... } # everything else
    
  • Плохая перегрузка оператора

    package my_object;
    use overload
      '+' => \&add,
      ...
    ;
    

    В Perl6 написано:

    multi sub infix:<+> (Us $us, Them $them) |
                        (Them $them, Us $us) { ... }
    

Я буду делать PHP так, как мне нравится, и Python будет слишком много.

  • Нет пространства имен; все в каком-то очень большом пространстве имен, которое ад в больших средах

  • Отсутствие стандартов в отношении функций: функции массива принимают иглу в качестве первого аргумента, стог сена - в качестве второго (см. Array_search). Строковые функции часто берут стог сена, а иглу - вторую (см. Стр.). Другие функции просто используют разные схемы именования: bin2hex, strtolower, cal_to_jd

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

    $var = preg_match_all('/regexp/', $str, $ret);
    echo $var; //outputs the number of matches 
    print_r($ret); //outputs the matches as an array
    
  • Язык (до PHP6) делает все возможное, чтобы уважать почти отсталую обратную совместимость, заставляя его нести плохие практики и функции, когда в этом нет необходимости (см. Mysql_escape_string и mysql_real_escape_string).

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

  • Это отстой при импорте файлов. У вас есть 4 различных способа сделать это (включая, include_once, require, require_once), все они медленные, очень медленные. На самом деле весь язык медленный. По крайней мере, довольно медленно, чем Python (даже с фреймворком) и RoR из того, что я собираю.

Я все еще люблю PHP, хотя. Это цепная пила веб-разработки: вы хотите, чтобы сайт от маленького до среднего выполнялся очень быстро и был уверен, что кто-нибудь может его разместить (хотя конфигурации могут отличаться)? PHP прямо здесь, и он настолько вездесущ, что требуется всего 5 минут, чтобы установить полный стек LAMP или WAMP. Ну, я сейчас вернусь к работе с Python...

Вот некоторые вещи, которые мне не нравятся в Java (это не мой любимый язык):

  • Стирание типа дженериков (т.е. нет дженериков)
  • Невозможность отловить несколько исключений (разных типов) в одном блоке перехвата
  • Отсутствие деструкторов (finalize () - очень плохая замена)
  • Нет поддержки для замыканий или обработки функций как данных (анонимные внутренние классы являются очень многословной заменой)
  • Проверка исключений в целом или, более конкретно, проверка неустранимых исключений (например, SQLException)
  • Нет языковой поддержки для литеральных коллекций
  • Отсутствие вывода типов при вызове конструкторов обобщенных классов, т. Е. Параметр (ы) типа должен повторяться по обе стороны от '='

C++

  1. Синтаксис шаблона
  2. Проблемы наследования бриллиантов
  3. Изобилие / отсутствие стандартных библиотек, которые есть в современных языках (хотя повышение уже близко).
  4. IOStreams
  5. Синтаксис, используемый вокруг IOStreams

питон

  1. Пробелы имеют смысл (иногда)
  2. ключевые слова с подчеркиванием
  3. Ограниченная поддержка потоков (по крайней мере, в настоящее время)
  4. "я" вместо "это"
  5. Пробелы имеют смысл (иногда)

Objective-C

1) Нет пространств имен, только соглашения по именованию вручную - я не возражаю против этого с точки зрения разделения классов, но мне не хватает возможности импортировать все определения классов в пространстве имен в одной строке (например, import com.me.somelibrary. *).

2) В библиотеках все еще есть дыры в важных областях, таких как поддержка RegEx.

3) Синтаксис свойства немного неуклюжий, требующий три строки (в двух отдельных файлах) для объявления свойства.

4) Мне нравится модель сохранения / выпуска, но проще выпустить ссылку, а затем случайно использовать ее позже.

5) Хотя Xcode на самом деле не является языковой функцией, она настолько переплетена с использованием Objective-C, что я не могу не думать об этом аспекте... в основном автозаполнение очень сомнительно. Это больше похоже на систему, которая вознаграждает вас за то, что вы нашли то, что вы хотите, существует, а затем представляет это как выбор. Но тогда я полагаю, мне никогда не нравились двигатели с автозаполнением.

C++

  • Строки.
    Они не совместимы со строками платформы, поэтому в итоге вы используете std::vector половину времени. Политика копирования (копирование при записи или глубокое копирование) не определена, поэтому нельзя дать гарантии производительности для простого синтаксиса. Иногда они полагаются на алгоритмы STL, которые не очень интуитивно понятны в использовании. Слишком много библиотек катят свои собственные, которые, к сожалению, намного более удобны в использовании. Если вы не должны объединить их.

  • Разнообразие строковых представлений
    Теперь, это небольшая проблема с платформой - но я все еще надеюсь, что было бы лучше, если бы раньше был доступен менее упрямый стандартный класс строк. Следующие строковые представления, которые я часто использую:

    • универсальный LPCTSTR,
    • LPC (W) STR, выделенный CoTaskMemAlloc,
    • BSTR, _bstr _t
    • (Ж) строка,
    • CString,
    • станд:: вектор
    • класс roll-my-own (sigh), который добавляет проверку диапазона и основные операции в буфер (w)char * известной длины
  • Построить модель.
    Я до смерти устал от того, что все время тратился на перепутывание с "кто включает в себя, что", предварительными объявлениями, оптимизацией предварительно скомпилированных заголовков и включений, чтобы поддерживать как минимум добавочные времена сборки терпимыми и т. Д. Это было здорово в восьмидесятых, но сейчас? Есть так много препятствий для упаковки кода, чтобы его можно было использовать повторно, чтобы даже маме собаке стало скучно слушать меня.

  • Трудно разобрать
    Это делает внешние инструменты особенно сложными для написания и получения правильных результатов. И сегодня нам, ребятам из C++, не хватает в основном цепочки инструментов. Я люблю свое отражение в C# и делегатов, но я могу жить без них. Без большого рефакторинга я не могу.

  • Threading слишком сложно
    Язык даже не распознает это (на данный момент), и свободы компилятора - хотя и велики - очень болезненны.

  • Статическая инициализация и инициализация по требованию. Технически, я обманываю здесь: это еще одна часть головоломки в "коде повторного использования": это кошмар, чтобы получить что-то инициализированное только тогда, когда это необходимо. Лучшее решение всех других проблем с переадресацией - это бросить все в заголовки, эта проблема говорит: "Нет, вы не можете".


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

JavaScript:

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

  • Все объекты являются хеш-картами, но их безопасно использовать как таковые. В частности, если один из ваших ключей окажется __proto__, ты в беде.

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

    • Следствие: вызов функции без обозначения объекта или new оператор приводит к this будучи установлен равным глобальному объекту, в результате чего много поломок.
  • Оператор сложения перегружен для выполнения конкатенации строк, несмотря на то, что эти две операции принципиально различаются. Причиняет боль, когда значение, которое вы ожидаете получить, на самом деле является строкой.

  • == а также != операторы выполняют приведение типов. Сравнения между различными типами включают в себя список правил, которые ни один смертный не может запомнить полностью. Это смягчается существованием === а также !== операторы.

  • И то и другое null а также undefined существуют, с немного различными, но избыточными значениями. Зачем?

  • Странный синтаксис для настройки цепочек прототипов.

  • parseInt(s) ожидает число в стиле C, поэтому рассматривает значения с начальными нулями как восьмеричные и т. д. Вы можете по крайней мере parseInt(s, 10) но поведение по умолчанию сбивает с толку.

  • Нет области видимости блока.

  • Может объявлять одну и ту же переменную более одного раза.

  • Может использовать переменную, не объявляя ее, в этом случае она является глобальной и, вероятно, нарушает вашу программу.

  • with { },

  • Действительно сложно документировать с помощью инструментов, подобных JavaDoc.

Python:

  • Отсутствие статической типизации
  • Обработка аргументов по умолчанию (особенно тот факт, что вы можете изменить аргумент по умолчанию для будущих абонентов!)
  • Слишком много обязательных подчеркиваний (нужно вызывать конструкторы __init__)
  • Отсутствие надлежащих закрытых членов и функций (соглашение просто говорит, что большинство вещей, которые начинаются с подчеркивания, являются частными, за исключением всего, что __getattr__ это не так)
  • Забавный синтаксис для print в файл (но они исправляют это в Python 3)

C#

  • Мне бы хотелось, чтобы я мог switch() на любой тип, и это case может быть любое выражение.

  • Нельзя использовать синтаксис инициализатора объекта с полями "только для чтения" / private set автосвойства. Как правило, мне нужна языковая помощь в создании неизменяемых типов.

  • Использование {} для пространства имен и класса, а также метода и блоков свойств / индексаторов, блоков с несколькими операторами и инициализаторов массива. Трудно понять, где вы находитесь, когда они далеко друг от друга или не соответствуют друг другу.

  • Я ненавижу писать (from x in y ... select).Z(), Я не хочу возвращаться к синтаксису вызова метода, потому что в синтаксисе запроса что-то отсутствует.

  • я хочу do пункт о синтаксисе запроса, который похож на foreach, Но тогда это не совсем вопрос.

Я действительно достигаю здесь. Я думаю, что C# - это фантастика, и трудно найти что-то сломанное.

PHP

  1. Нет функций отладки, если вы не контролируете сервер, и даже тогда они отстой
  2. Огромное количество плохого PHP-кода дает плохое имя всем программистам PHP
  3. Непоследовательная функция именования
  4. Невозможность иметь статическую типизированную переменную, если она мне нужна (я большой поклонник динамической типизации в 90% случаев)
  5. REGISTER_GLOBALS это дьявол

C (ОК, это не мой любимый, но это еще не было сделано.)

  • Синтаксис библиотеки сокетов.
  • Нет перегрузки функции.
  • Струны в стиле C
  • Переполнение буфера.
  • Загадочный синтаксис. Я не знаю, сколько раз я смотрел такие вещи, как атой, хлопал себя по лбу и кричал "Конечно!"

РЕДАКТИРОВАТЬ: Я мог бы, вероятно, придумать больше, если бы я прибегнул к большему количеству библиотечного кода (как я сделал с сокетами, но это особенно плохо), но я уже чувствовал, что я обманываю для выбора на C. Так много языков существует только для хорошие части C и заменить плохие, что это похоже на избиение мертвой лошади.

BrainF* ск

  • Ваш основной момент в том, что вы завершили Тьюринг?! Я могу сделать больше в регулярных выражениях Perl!

  • Отсутствие предметов. Да ладно, люди! Это как, привет...

  • Нет сетевых библиотек. Все, что я хочу, это очистить веб-страницу, GOSH.

  • Нет первоклассных функций. Поздравляем - вы можете поболтать с друзьями по Java.

  • Бесконечная лента для хранения и ничего больше. Это настолько анально претенциозно, что мы могли бы написать Лисп.

Common Lisp:

  1. Ключевые слова часто слишком многословны.
  2. Поддержка библиотеки жалкая.
  3. Не работает в ОС, которые хотят более строго обрабатывать память.
  4. Не имеет хороших возможностей для взаимодействия с ОС.
  5. Средство "loop" не очень хорошо определено и, конечно, не выглядит Lispy.

JavaScript

  1. числа как строки - Математика может расстраивать, когда числа интерпретируются как строки. 5 + 2 = 52? Хмм...
  2. разрешения - все самое лучшее требует разрешения от пользователя!
  3. обновления экрана - браузер должен находиться в устойчивом состоянии для обновления экрана. Кажется, нет способа заставить экран обновляться в середине скрипта.
  4. Медленно - хотя Google Chrome хорош...
  5. Различия в браузерах делают использование языка цензурой.

PHP:

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

Тем не менее, PHP является (скриптовым) языком.;-)

Ruby - мой любимый язык, вот что мне не нравится:

  • Зеленые потоки + блокировка библиотек C = гигантский сбой
  • ТАК БЕЗУМНО МЕДЛЕННО
  • Сама стандартная библиотека несовместима с использованием взрыва! методы
  • Модуль включает в себя + расширение является грязным.
  • "Открытые классы" не могут быть ограничены - я хочу добавить String#dostuff, но я не хочу, чтобы это просачивалось во все сторонние библиотеки
  • Нет бинарного решения для развертывания пакетов.

VB6

  1. Только для Windows
  2. Больше не поддерживается.
  3. Массивы могут начинаться с любого числа, а не нормализоваться до 0.
  4. скомпилированные приложения зависят от того, как много DLL работают правильно.
  5. Многие сложные элементы управления, такие как элемент управления браузера или сложные фрагменты кода, имеют тенденцию нарушать IDE, когда вы запускаете код без компиляции, но прекрасно работают при компиляции.

Delphi:

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

JavaScript

  • Каждый сценарий выполняется в едином глобальном "пространстве имен"... то, на что вы должны обращать внимание при работе со сценариями из разных источников.

  • Если переменная используется, но не была определена ранее, она считается глобальной переменной

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

  • Чувствительность к регистру - учитывая, что не существует достойной IDE для разработки js с проверкой во время компиляции

  • Обходные пути (такие как использование hasOwnProperty метод) для выполнения некоторых, в противном случае простых операций.

Haskell:

  1. Космические утечки из ленивой оценки.
  2. Числовая иерархия не построена с учетом математических абстракций.
  3. Строгое монадическое IO может затруднить отладку.
  4. Большие реализации обрабатывают ввод / вывод способами, которые не совсем совместимы со стандартом. (В частности, при выводе символов выводятся только младшие 8 битов, а затем создается код, который использует это допущение для выполнения двоичного ввода-вывода. Ick.)
  5. Ассоциативность ($) оператор может быть изменен, чтобы сделать некоторые выражения красивее.

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

Изменить: Там было некоторое замешательство по поводу пункта 5. В частности, некоторые люди, кажется, думают, что я имел в виду порядок аргументов, что я не делаю. Вместо того, чтобы объяснять, что я имел в виду, я просто укажу людям на следующую ссылку, http://hackage.haskell.org/trac/haskell-prime/wiki/ChangeDollarAssociativity, которая хорошо это выражает.

Другие вопросы по тегам