Говнокод ли это?
От: YetAnotherOne  
Дата: 19.08.11 14:23
Оценка:
Как вы считаете, является ли данный класс говнокодом? Если бы вам предложили поддерживать проект с подобным кодом, вы бы были в восторге или огорчились бы? По сравнению с качеством кода в вашей конторе хуже или лучше? Во сколько бы оценили по 5-ти бальной шкале?

Код:

public class HttpStream
    {
        private readonly HttpHeaders _headers;
        private readonly string _body;

        internal HttpHeaders Headers
        {
            get { return _headers; }
        }

        [CanBeNull]
        internal string Body
        {
            get { return _body; }
        }

        [CanBeNull]
        internal Encoding BodyEncoding { get; private set; }

        private HttpStream(StreamReader streamReader, HttpHeaders httpHeaders)
        {
            if (streamReader == null)
                throw new ArgumentNullException("streamReader");
            if (httpHeaders == null)
                throw new ArgumentNullException("httpHeaders");

            _headers = httpHeaders;
            _body = readBody(streamReader);
        }

        internal static HttpStream ParseRequest(StreamReader streamReader)
        {
            if (streamReader == null)
                throw new ArgumentNullException("streamReader");

            return new HttpStream(streamReader, new HttpRequestHeaders(streamReader));
        }

        internal static HttpStream ParseResponse(StreamReader streamReader)
        {
            if (streamReader == null)
                throw new ArgumentNullException("streamReader");

            return new HttpStream(streamReader, new HttpResponseHeaders(streamReader));
        }

        private string readBody(StreamReader streamReader)
        {
            var contentType = _headers["Content-Type"];
            if (!string.IsNullOrWhiteSpace(contentType))
            {
                foreach (var section in contentType.Split(';'))
                {
                    var parts = section.Split('=');
                    var name = parts[0].Trim();
                    switch (name.ToLowerInvariant())
                    {
                        case "charset":
                            BodyEncoding = Encoding.GetEncoding(parts[1].Trim());
                            break;
                    }
                }
            }

            var isChunked = false;
            var chunked = _headers["Transfer-Encoding"];
            if (!string.IsNullOrWhiteSpace(chunked))
            {
                isChunked = true;
            }

            Stream compressedStream = null;
            Stream deChunkedStream = null;

            try
            {
                var stream = streamReader.BaseStream;

                setPositionToBody(stream);

                if (isChunked)
                {
                    stream = deChunkeToNewStream(stream);
                    deChunkedStream = stream;
                    stream.Position = 0;
                }

                var contentEncoding = _headers["Content-Encoding"];
                if (!string.IsNullOrWhiteSpace(contentEncoding))
                {
                    switch (contentEncoding)
                    {
                        case "gzip":
                            stream = new GZipStream(stream, CompressionMode.Decompress, true);
                            compressedStream = stream;
                            break;
                        case "deflate":
                            stream = new DeflateStream(stream, CompressionMode.Decompress, true);
                            compressedStream = stream;
                            break;

                        default:
                            try
                            {
                                // путают настройщики серверов Content-Encoding с Content-Type
                                var dummyEncoding = Encoding.GetEncoding(contentEncoding);

                                if (BodyEncoding == null)
                                    BodyEncoding = dummyEncoding;
                            }
                            catch (ArgumentException)
                            {
                                throw new InvalidOperationException("Не известное значение заголовка Content-Encoding:" +
                                                                    contentEncoding);
                            }
                            break;
                    }
                }

                using (var bodyReader = new StreamReader(stream, BodyEncoding ?? Encoding.UTF8))
                {
                    return bodyReader.ReadToEnd();
                }
            }
            finally
            {
                if (deChunkedStream != null)
                {
                    deChunkedStream.Dispose();
                }
                if (compressedStream != null)
                {
                    compressedStream.Dispose();
                }
            }
        }

        private static Stream deChunkeToNewStream(Stream stream)
        {
            var hexSize = string.Empty;

            Stream resStream = new MemoryStream();
            int readed;
            do
            {
                var buf = new byte[1];
                readed = stream.Read(buf, 0, 1);
                if (readed == 1 && buf[0] == 13)
                {
                    readed = stream.Read(buf, 0, 1);
                    if (readed == 1 && buf[0] == 10)
                    {
                        // копируем тело чанка в результирующий поток
                        var chunkSize = int.Parse(hexSize, NumberStyles.AllowHexSpecifier);
                        var chunkBuf = new byte[chunkSize];
                        readed = stream.Read(chunkBuf, 0, chunkSize);
                        if (readed != chunkSize)
                        {
                            throw new InvalidOperationException(
                                string.Format("Ошибка чтения. Ожидалось байт: {0}; Получено: {1}", chunkSize, readed));
                        }
                        resStream.Write(chunkBuf, 0, chunkSize);

                        hexSize = string.Empty;

                        // пропускаем CRLF, идущий после каждого чанка
                        readed = stream.Read(buf, 0, 1);
                        if (readed == 1 && buf[0] == 13)
                        {
                            readed = stream.Read(buf, 0, 1);
                            if (readed == 1 && buf[0] == 10)
                            {
                                continue;
                            }
                        }
                        throw new InvalidOperationException("Чанк не оканчивается на #13#10");
                    }
                    throw new InvalidOperationException("Не ожиданный символ #13, без последующего #10");
                }

                hexSize += (char) buf[0];
            } while (readed > 0);

            return resStream;
        }

        private static void setPositionToBody(Stream stream)
        {
            stream.Position = 0;

            var buf = new byte[1];
            int readed;
            do
            {
                // читаем до 2 подряд идущих CRLF
                readed = stream.Read(buf, 0, 1);
                if (readed != 1 || buf[0] != 13)
                {
                    continue;
                }
                readed = stream.Read(buf, 0, 1);
                if (readed != 1 || buf[0] != 10)
                {
                    continue;
                }
                readed = stream.Read(buf, 0, 1);
                if (readed != 1 || buf[0] != 13)
                {
                    continue;
                }
                readed = stream.Read(buf, 0, 1);
                if (readed == 1 && buf[0] == 10)
                {
                    return;
                }
            } while (readed > 0);
        }
    }
Re: Говнокод ли это?
От: Lloyd Россия  
Дата: 19.08.11 14:32
Оценка: 1 (1) +11
Здравствуйте, YetAnotherOne, Вы писали:

YAO>Как вы считаете, является ли данный класс говнокодом? Если бы вам предложили поддерживать проект с подобным кодом, вы бы были в восторге или огорчились бы? По сравнению с качеством кода в вашей конторе хуже или лучше? Во сколько бы оценили по 5-ти бальной шкале?


Это просто конфетка по сравнению с тем, с чем приходится работать. Поставил бы твердую 4+.
Re: Говнокод ли это?
От: _AND Российская Империя За Русский мир! За Русь святую!
Дата: 19.08.11 14:46
Оценка: +2
Здравствуйте, YetAnotherOne, Вы писали:

YAO>Как вы считаете, является ли данный класс говнокодом? Если бы вам предложили поддерживать проект с подобным кодом, вы бы были в восторге или огорчились бы? По сравнению с качеством кода в вашей конторе хуже или лучше? Во сколько бы оценили по 5-ти бальной шкале?


YAO>Код:


В логику сильно не вникал. На первый взгляд — обычный, нормальный код. Оценка 4+
Re: Говнокод ли это?
От: UA Украина  
Дата: 19.08.11 14:50
Оценка:
Здравствуйте, YetAnotherOne, Вы писали:

Без goto тянет только на 3-
Re: Говнокод ли это?
От: Доктор ТуамОсес Гондурас Мой новый проект "ВЕПРЬ-1"
Дата: 19.08.11 15:34
Оценка:
Здравствуйте, YetAnotherOne, Вы писали:

YAO>Говнокод ли это?

Такие вопросы лучше завать ТУТ
Мой новый проект "ВЕПРЬ-1"
Re: Говнокод ли это?
От: boot  
Дата: 19.08.11 15:44
Оценка: 4 (2) +1
Здравствуйте, YetAnotherOne, Вы писали:

YAO>Как вы считаете, является ли данный класс говнокодом? Если бы вам предложили поддерживать проект с подобным кодом, вы бы были в восторге или огорчились бы? По сравнению с качеством кода в вашей конторе хуже или лучше? Во сколько бы оценили по 5-ти бальной шкале?


Не понимаю, что заставляет людей так думать и писать. Может язык совместно с фрэймворком? Не понимаю, зачем объединять поток и структуру запроса/ответа в один класс. Может только чтобы потом написать application.run().
Оценку ставить не берусь, пока кто-нибудь не объяснит где это так надо.
Жизнеспособность прямо пропорциональна простоте!
Re: Говнокод ли это?
От: elmal  
Дата: 19.08.11 15:55
Оценка:
Здравствуйте, YetAnotherOne, Вы писали:

YAO>Как вы считаете, является ли данный класс говнокодом? Если бы вам предложили поддерживать проект с подобным кодом, вы бы были в восторге или огорчились бы? По сравнению с качеством кода в вашей конторе хуже или лучше? Во сколько бы оценили по 5-ти бальной шкале?

Тут интересный вопрос. Свой худший код, который писался часто в ASAP режиме я оцениваю на 3 или 3- (копипасту я даже в ASAP режиме не допускаю, бывает спускаюсь и ниже удовлетворительного, но в таком состоянии код живет не больше недели, потом меня совесть замучит). Максимальную оценку себе я выше 4 еще не ставил. А на код, которому можно 5 поставить, я бы просто хотел бы посмотреть — всегда есть простор к улучшению .
Уроверь писавшего оцениваю как юниорский. Код бы я оценил на 2, то есть неудовлетворительно, но не смертельно. Тт человека, с опытом меньше двух лет, как показывает практика, лучшего кода ожидать бессмысленно. Это не такая плохая оценка, худший код, который я видел, я б оценил в 0 из 5 (писали американские студенты). А этот можно довольно быстро привести к удовлетворительному состоянию, если поизбавляться от некоторой копипасты, сократить и повысить понятность можно легко, более глубоко даже лень смотреть пока не отрефакторю.
Предполагаю, что это код тестового задания. Соответственно студента, сильному в теории и написавшего подобный код я бы взял на юниора, переучить можно. Если б такое написал кто-то, претендующий на хорошего разработчика — извините, есть куча других контор, которых этот код удовлетворит в полной мере (да там и кодировать не попросят, максимум на бумажке, где по нормальному один хрен не напишешь), у нас он просто не впишется в коллектив.
Если бы мне предложили поддерживать проект с подобным кодом за 200 тысяч в месяц я б обрадовался. За 120 тысяч я б подумал. За 100 тысяч — твердо б не согласился. Но в конторах с таким кодом мне и 50 не предложат .
Re: Говнокод ли это?
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 19.08.11 16:00
Оценка:
Здравствуйте, YetAnotherOne, Вы писали:

YAO>Как вы считаете, является ли данный класс говнокодом? Если бы вам предложили поддерживать проект с подобным кодом, вы бы были в восторге или огорчились бы? По сравнению с качеством кода в вашей конторе хуже или лучше? Во сколько бы оценили по 5-ти бальной шкале?


Троечка. В принципе это код хорошего джуниора
Re[2]: Говнокод ли это?
От: Vzhyk  
Дата: 19.08.11 16:03
Оценка: 1 (1) +4
19.08.2011 18:55, elmal пишет:

> Тут интересный вопрос. Свой худший код, который писался часто в ASAP

> режиме я оцениваю на 3 или 3- (копипасту я даже в ASAP режиме не
> допускаю, бывает спускаюсь и ниже удовлетворительного, но в таком
> состоянии код живет не больше недели, потом меня совесть замучит).
> Максимальную оценку себе я выше 4 еще не ставил.
Ты бы свой код сюда выложил. Мы бы посмотрели, обос... обсудили.
Posted via RSDN NNTP Server 2.1 beta
Re[2]: А слабо этот говнокод превратить в конфетку?
От: gyraboo  
Дата: 19.08.11 16:10
Оценка:
Здравствуйте, Доктор ТуамОсес, Вы писали:

YAO>>Говнокод ли это?

ДТ>Такие вопросы лучше завать ТУТ

Дохтур, прошу показать мастер-класс на данном примере и реально утреть наконец-таки нос вашим недоброжелателям и тролле-изличителям.

1. Анализ данного примера, выявление проблем
2. Обоснованный рефакторинг
Re[2]: Говнокод ли это?
От: Доктор ТуамОсес Гондурас Мой новый проект "ВЕПРЬ-1"
Дата: 19.08.11 16:14
Оценка:
Если у Вас много гавнокода, то обращайтесь ко мне. Помогу.
РАБОТАЮ С ГАВНОКОДОМ! ДЁШЕВО
Автор: Доктор ТуамОсес
Дата: 03.08.11
Мой новый проект "ВЕПРЬ-1"
Re[2]: Говнокод ли это?
От: Ikemefula Беларусь http://blogs.rsdn.org/ikemefula
Дата: 19.08.11 16:15
Оценка:
Здравствуйте, boot, Вы писали:

B>Не понимаю, что заставляет людей так думать и писать. Может язык совместно с фрэймворком? Не понимаю, зачем объединять поток и структуру запроса/ответа в один класс. Может только чтобы потом написать application.run().


Потому что для джуниоров
1 это предельно наглядно, т.к. все еще слабо решают задачи, что бы делать это в уме, соответсвенно код своего рода черновик
2 еще не научились декомпозиции, например выделять определенные обязанности
3 не понимают все имеющиеся проблемы в таком коде
4 не правильно оценивают важность известных им проблем
Re[2]: Говнокод ли это?
От: YetAnotherOne  
Дата: 19.08.11 18:56
Оценка: 4 (1) +1
Здравствуйте, Lloyd, Вы писали:

L>Это просто конфетка по сравнению с тем, с чем приходится работать. Поставил бы твердую 4+.


Вы не шутите? То есть вы считаете, что это вполне нормально:

1. Поведение. Что это за класс вообще? Вроде Stream (HttpStream), но по сути дела никакой не Stream, а скорее Reader. И то сомнительно -- т.к. в нем и заголовки, и тело запроса в виде строки. Поведение размазано.

2. Парсить в этом Stream HTTP-заголовки (хотя есть класс HttpHeaders, HttpRequestHeaders, HttpResponseHeaders):

Вот:

var contentType = _headers["Content-Type"];
            if (!string.IsNullOrWhiteSpace(contentType))
            {
                foreach (var section in contentType.Split(';'))
                {
                    var parts = section.Split('=');
                    var name = parts[0].Trim();
                    switch (name.ToLowerInvariant())
                    {
                        case "charset":
                            BodyEncoding = Encoding.GetEncoding(parts[1].Trim());
                            break;
                    }
                }
            }


и вот:

  var isChunked = false;
            var chunked = _headers["Transfer-Encoding"];
            if (!string.IsNullOrWhiteSpace(chunked))
            {
                isChunked = true;
            }


и вот:


 var contentEncoding = _headers["Content-Encoding"];
                if (!string.IsNullOrWhiteSpace(contentEncoding))
                {
 switch (contentEncoding)
                    {
                        case "gzip":
                           ...
                            break;
                        case "deflate":
                            ...
                            break;



3. Вот такая конструкция:

return new HttpStream(streamReader, new HttpRequestHeaders(streamReader));


как вам? То есть в HttpStream парсим заголовки, а в HttpRequestHeaders и HttpResponseHeaders читаем поток.

4. При чтении в методе readBody закрываем основной поток. При этом иногда он будет закрыт, а иногда нет:

 using (var bodyReader = new StreamReader(stream, BodyEncoding ?? Encoding.UTF8))


5. Как вам функция deChunkeToNewStream? Не находите, что это можно написать намного проще?

6. Как вам функция setPositionToBody? И вообще насколько она уместна, если после заголовка всегда идет body?

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

Или поставили 4+ как для Junior?
Re[3]: Говнокод ли это?
От: Lloyd Россия  
Дата: 19.08.11 19:28
Оценка: 1 (1) +3
Здравствуйте, YetAnotherOne, Вы писали:

L>>Это просто конфетка по сравнению с тем, с чем приходится работать. Поставил бы твердую 4+.


YAO>Вы не шутите? То есть вы считаете, что это вполне нормально:


А я смысл не читал, только код посмотрел.
И таки-да, по сравнению с тем, с чем приходится работать, код-таки конфетка.
Re: Говнокод ли это?
От: andrey.t  
Дата: 19.08.11 19:40
Оценка: 1 (1)
Здравствуйте, YetAnotherOne, Вы писали:

YAO>Как вы считаете, является ли данный класс говнокодом? Если бы вам предложили поддерживать проект с подобным кодом, вы бы были в восторге или огорчились бы? По сравнению с качеством кода в вашей конторе хуже или лучше? Во сколько бы оценили по 5-ти бальной шкале?


YAO>Код:


YAO>
YAO>


1. Если говорить про качество кода на уровне функции, то это очень хороший код — исключения и работа с ресурсами на месте, всё однообразно в соответствии с некоторыми правилами оформления кода. При желании можно быстро понять и разобраться. 4 из 5.

2. Если смотреть на класс сверху и начинать придиратся, то ни разу не Stream никакой. Да и закрытая readBody(), которая только в конструкторе дергается никак тестированию не поддается. Но на самом деле это — мелочи, которые наоборот только тянет улучшить, но никак не бежать в панике от этого кода, если таковой достанется.
Re: Говнокод ли это?
От: tovarish_n  
Дата: 19.08.11 19:43
Оценка:
Здравствуйте, YetAnotherOne, Вы писали:

Жить можно. 4.
Re: Говнокод ли это?
От: Tom Россия http://www.RSDN.ru
Дата: 19.08.11 20:22
Оценка: 1 (1)
Здравствуйте, YetAnotherOne, Вы писали:

YAO>Как вы считаете, является ли данный класс говнокодом? Если бы вам предложили поддерживать проект с подобным кодом, вы бы были в восторге или огорчились бы? По сравнению с качеством кода в вашей конторе хуже или лучше? Во сколько бы оценили по 5-ти бальной шкале?

Я бы сказал что структура кода конечно не лучшая, видно полное несоблюдение SOLID, функции имееют по 5-8 ответственностей. Но в целом код поддётся простому рефакторингу. По 5-ти бальной системе поставил бы твёрдую 3-ку.
Народная мудрось
всем все никому ничего(с).
Re: Говнокод ли это?
От: abibok  
Дата: 19.08.11 23:05
Оценка:
YAO>Как вы считаете, является ли данный класс говнокодом? Если бы вам предложили поддерживать проект с подобным кодом, вы бы были в восторге или огорчились бы? По сравнению с качеством кода в вашей конторе хуже или лучше? Во сколько бы оценили по 5-ти бальной шкале?

Код не очень хорош, есть замечания и по стилю, и по структуре, и по реализации. Но приходилось работать и с намного более плохим кодом, так что все не очень страшно. 4-
Re: readed?
От: qqqqq  
Дата: 19.08.11 23:45
Оценка:
мне бросились в глаза переменные под названием readed. Это "считано" в пререводе на рунглиш?
Re[3]: Говнокод ли это?
От: elmal  
Дата: 20.08.11 03:34
Оценка:
Здравствуйте, Vzhyk, Вы писали:

V>Ты бы свой код сюда выложил. Мы бы посмотрели, обос... обсудили.

Код проекта, увы, выкладывать нет желания на всеобщее обозрение. А код проваленного простого тестового задания, на который даже фидбека никакого не получил, как то даже выкладывал здесь
Автор: elmal
Дата: 20.12.09
.
Здесь ИМХО ближе к 4-м, старался.
Ну а ASAP реализация одной специфичной задачи, которую оцениваю сам на 3-, и которую возможно потребуется полность переписать или вообще выкинуть (скорее второе):
/**
 * Заточенный под поиск свой велосипед. Позволяет искать следующий и предыдущий открытый тег с любого
 * места как вперед, так и назад. Собственно даже не XML здесь ищется, а любые теги
 */
public class CustomXMLParser {
    public TagPosition findPreviousTag(String content, int startPosition) {
        return findPreviousTag(content, startPosition, 1);
    }

    public TagPosition findPreviousTag(String content, int startPosition, int neededToFindOpenTags) {
        TagPosition tag = null;
        int currentPosition = startPosition;
        while (neededToFindOpenTags > 0) {
            tag = findPreviousTagPosition(content, currentPosition);
            currentPosition = tag.getOpenTagPosition() - 1;
            if (tag.isOpenTag()) {
                neededToFindOpenTags--;
            } else {
                neededToFindOpenTags++;
            }
        }
        return tag;
    }

    public TagPosition findNextTag(String content, int startPosition) {
        int neededToFindCloseTags = 1;
        TagPosition tag = null;
        int currentPosition = startPosition;
        while (neededToFindCloseTags > 0) {
            tag = findNextTagPosition(content, currentPosition);
            currentPosition = tag.getCloseTagPosition() + 1;
            if (tag.isOpenTag()) {
                neededToFindCloseTags++;
            } else {
                neededToFindCloseTags--;
            }
        }
        return tag;
    }

    private TagPosition findPreviousTagPosition(String content, int startPosition) {
        TagPosition result = new TagPosition();
        result.setOpenTagPosition(0);
        result.setCloseTagPosition(startPosition);
        boolean found = false;

        for (int i = startPosition; i > 0; --i) {
            char chr = content.charAt(i);
            if (chr == '>') {
                result.setCloseTagPosition(i);
                if (content.charAt(i - 1) != '/') {
                    found = true;
                }
            }
            if (chr == '<') {
                result.setOpenTagPosition(i);
                if (found) {
                    break;
                }
            }
        }
        String foundedTag = content.substring(result.getOpenTagPosition(), result.getCloseTagPosition() + 1);
        if (foundedTag.contains("/")) {
            result.setOpenTag(false);
        } else {
            result.setOpenTag(true);
        }
        return result;
    }

    private TagPosition findNextTagPosition(String content, int startPosition) {
        TagPosition result = new TagPosition();
        result.setOpenTagPosition(0);
        result.setCloseTagPosition(startPosition);

        for (int i = startPosition; i < content.length(); ++i) {
            char chr = content.charAt(i);
            if (chr == '>') {
                result.setCloseTagPosition(i);
                if (content.charAt(i - 1) != '/') {
                    break;
                }
            }
            if (chr == '<') {
                result.setOpenTagPosition(i);
            }
        }
        String foundedTag = content.substring(result.getOpenTagPosition(), result.getCloseTagPosition() + 1);
        if (foundedTag.contains("/")) {
            result.setOpenTag(false);
        } else {
            result.setOpenTag(true);
        }
        return result;
    }
}

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