laconic vs. verbose
От: igna Россия  
Дата: 16.05.06 08:40
Оценка:
Какую из двух приведенных ниже программ труднее понять без комментариев?

using System;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
using System.Web;

class Program
{
    static void Main(string[] args) {
        try {
            if (args.Length == 1) {
                WebRequest request =
                    WebRequest.Create("http://www.comeaucomputing.com/pcgi-bin/compiler.cgi");
                request.Method = "POST";
                using (StreamWriter requestWriter = new StreamWriter(request.GetRequestStream())) {
                    requestWriter.Write("Tused=-tused&Strict=-A&Version=433&Comment=");
                    using (StreamReader sourceTextReader = new StreamReader(args[0]))
                        requestWriter.Write(HttpUtility.UrlEncode(sourceTextReader.ReadToEnd()));
                }
                using (StreamReader responseReader =
                        new StreamReader(request.GetResponse().GetResponseStream()))
                    HttpUtility.HtmlDecode(new Regex("<pre>([^<]*)</pre>")
                        .Match(responseReader.ReadToEnd()).Groups[1].Value, Console.Out);
            }
            else
                Console.WriteLine("Syntax: comoc filename");
        }
        catch (Exception e) {
            Console.WriteLine(e.Message);
        }
    }
}


using System;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
using System.Web;

class Program
{
    static void Main(string[] args) {
        try {
            if (args.Length == 1) {
                string filename = args[0];
                string sourceText;
                using (StreamReader sourceTextReader = new StreamReader(filename))
                    sourceText = sourceTextReader.ReadToEnd();

                const string compilerUri = "http://www.comeaucomputing.com/pcgi-bin/compiler.cgi";
                WebRequest request = WebRequest.Create(compilerUri);
                request.Method = "POST";
                using (StreamWriter requestWriter = new StreamWriter(request.GetRequestStream())) {
                    const string postDataConstPart = "Tused=-tused&Strict=-A&Version=433&Comment=";
                    requestWriter.Write(postDataConstPart);
                    requestWriter.Write(HttpUtility.UrlEncode(sourceText));
                }
                WebResponse response = request.GetResponse();
                string html;
                using (StreamReader responseReader = new StreamReader(response.GetResponseStream()))
                    html = responseReader.ReadToEnd();

                Regex compilerOutputRegex = new Regex("<pre>([^<]*)</pre>");
                string compilerOutput = compilerOutputRegex.Match(html).Groups[1].Value;
                HttpUtility.HtmlDecode(compilerOutput, Console.Out);
            }   
            else
                Console.WriteLine("Syntax: comoc filename");
        }
        catch (Exception e) {
            Console.WriteLine(e.Message);
        }
    }
}
Re: laconic vs. verbose
От: Banch  
Дата: 16.05.06 08:50
Оценка:
Здравствуйте, igna, Вы писали:

имхо второй вариант лучше, и дело не в лаконичности
во втором варианте шаги процесса лучше видны
Re: laconic vs. verbose
От: Hunta Украина http://dr-leafsey.livejournal.com
Дата: 16.05.06 09:15
Оценка: 1 (1) +1
Здравствуйте, igna, Вы писали:

I>Какую из двух приведенных ниже программ труднее понять без комментариев?


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

I>
I>                string filename = args[0];
I>


По моему так написать гораздо лучше чем вставтять комментарий типа "args[0] хранит имя файла".
Поступай так, чтобы максима своей воли в любое время могла стать принципом всеобщего законодательства.
Re: laconic vs. verbose
От: PhantomIvan  
Дата: 16.05.06 09:31
Оценка:
Здравствуйте, igna, Вы писали:

I>Какую из двух приведенных ниже программ труднее понять без комментариев?


...

Второй вариант понятнее тому, кто разбирает твой код, не зная его цели, т.к. переменные названы соотв. образом.
А если это ты сам его пишешь, или я вижу, что функция называется "Compile", то сразу понятно назначение этого куска кода — скомпилировать программу cgi-компилятором и вывести результат на консоль. Поэтому 2 варианта примерно одинаковы по экспрессии, и следует выбирать более лаконичный. С третьей стороны, имея решарпер, ctrl+alt+n (variable inlining) & ctrl+alt+v (variable introducing) решают проблему согласно эстетическому вкусу программиста.
... << RSDN@Home 1.1.4 stable SR1 rev. 568>>
Re: laconic vs. verbose
От: Vermicious Knid  
Дата: 16.05.06 12:44
Оценка: +3 :)
Здравствуйте, igna, Вы писали:

I>Какую из двух приведенных ниже программ труднее понять без комментариев?

На мой взгляд обе достаточно легко понять, но мне больше нравится вторая. А еще больше мне нравится вот это:
using System;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
using System.Web;
using Nemerle.Collections;

module Comoc
{
    executePostRequest(uri : string, params data : array[string]) : string
    {
        def request = WebRequest.Create(uri);
        request.Method = "POST";
        using (requestWriter = StreamWriter(request.GetRequestStream()))
            foreach(dataString in data)
                requestWriter.Write(dataString);

        def response = request.GetResponse();
        def responseText = 
            using (responseReader = StreamReader(response.GetResponseStream()))
                responseReader.ReadToEnd();
        responseText
    }

    Main(args : array[string]) : void
    {
        try
        {                
            match(List.FromArray(args))
            {
                | [filename] =>
                    def sourceText = 
                        using (sourceTextReader = StreamReader(filename))
                            sourceTextReader.ReadToEnd();

                    def compilerUri = "http://www.comeaucomputing.com/pcgi-bin/compiler.cgi";
                    def postDataConstPart = "Tused=-tused&Strict=-A&Version=433&Comment=";
                    def html = executePostRequest(compilerUri, postDataConstPart, 
                                HttpUtility.UrlEncode(sourceText));

                    def compilerOutputRegex = Regex("<pre>([^<]*)</pre>");
                    def compilerOutput = compilerOutputRegex.Match(html).Groups[1].Value;
                    HttpUtility.HtmlDecode(compilerOutput, Console.Out);
                                
                | _ => Console.WriteLine("Syntax: comoc filename");
            }
        }
        catch
        {
            | e => Console.WriteLine(e.Message);
        }
    }
}


Но это конечно мои личные предпочтения.
Re: laconic vs. verbose
От: Кодёнок  
Дата: 17.05.06 05:18
Оценка: +1 -1
Здравствуйте, igna, Вы писали:

I>Какую из двух приведенных ниже программ труднее понять без комментариев?


Мне первая более понятна.

А зачем в такой программе давать имена константам? compilerUri более понятно, чем "http://.../compiler.cgi" ? Или "Syntax: comoc filename" которая находится на этом же экране, на глазах, не сообщит что args[0] это имя файла?
Re: laconic vs. verbose
От: IT Россия linq2db.com
Дата: 18.05.06 01:23
Оценка: +3
Здравствуйте, igna, Вы писали:

I>Какую из двух приведенных ниже программ труднее понять без комментариев?


Первый вариант. А если его ещё и слегка модифицировать:

using System;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
using System.Web;

class Program
{
    static void Main(string[] args)
    {
        if (args.Length == 1)
        {
            Console.WriteLine("Syntax: comoc filename");
            return;
        }

        try
        {
            WebRequest request = WebRequest.Create("http://www.comeaucomputing.com/pcgi-bin/compiler.cgi");

            request.Method = "POST";

            using (StreamWriter sw = new StreamWriter(request.GetRequestStream()))
            using (StreamReader sr = new StreamReader(args[0]))
            {
                sw.Write("Tused=-tused&Strict=-A&Version=433&Comment={0}",
                    HttpUtility.UrlEncode(sr.ReadToEnd()));
            }

            using (StreamReader sr = new StreamReader(request.GetResponse().GetResponseStream()))
            {
                HttpUtility.HtmlDecode(
                    Regex.Match(sr.ReadToEnd(), "<pre>([^<]*)</pre>").Groups[1].Value,
                    Console.Out);
            }
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }
}
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: laconic vs. verbose
От: IT Россия linq2db.com
Дата: 18.05.06 01:55
Оценка:
Здравствуйте, Vermicious Knid, Вы писали:

VK>На мой взгляд обе достаточно легко понять, но мне больше нравится вторая. А еще больше мне нравится вот это:


Маньяк.
... << RSDN@Home 1.2.0 alpha rev. 0>>
Если нам не помогут, то мы тоже никого не пощадим.
Re[2]: laconic vs. verbose
От: ie Россия http://ziez.blogspot.com/
Дата: 18.05.06 02:31
Оценка:
Здравствуйте, Vermicious Knid, Вы писали:

VK>На мой взгляд обе достаточно легко понять, но мне больше нравится вторая. А еще больше мне нравится вот это:


Я бы еще вот этот кусочек подправил:

VK>
VK>    def compilerOutputRegex = Regex("<pre>([^<]*)</pre>");
VK>    def compilerOutput = compilerOutputRegex.Match(html).Groups[1].Value;
VK>


вот так вот:

    def compilerOutput = 
        regexp match (html) 
        {
            | "<pre>(?<output : string>[^<]*)</pre>" => output;
            | _ => "";
        }
... << RSDN@Home 1.1.4 beta 7 rev. 447>>
Превратим окружающую нас среду в воскресенье.
Re[2]: laconic vs. verbose
От: Кодёнок  
Дата: 18.05.06 06:07
Оценка:
Здравствуйте, VladD2, Вы писали:

Кё>Мне первая более понятна.


Кё>А зачем в такой программе давать имена константам? compilerUri более понятно, чем "http://.../compiler.cgi" ? Или "Syntax: comoc filename" которая находится на этом же экране, на глазах, не сообщит что args[0] это имя файла?


А с чем несогласился Влад? Я задал какой-то религиозно неправильный вопрос, что-ли Зачем давать?
Re[3]: laconic vs. verbose
От: Vermicious Knid  
Дата: 18.05.06 06:51
Оценка:
Здравствуйте, ie, Вы писали:

ie>вот так вот:

ie>
ie>        regexp match (html) 
ie>             ...
ie>


На самом деле у меня так и было. Но вот заставить эту конструкцию правильно работать в этом конкретном случае мне не удалось. Скорее всего баг в макросе, но мне лень было разбираться.
Re: laconic vs. verbose
От: GlebZ Россия  
Дата: 18.05.06 18:11
Оценка:
Здравствуйте, igna, Вы писали:

Мне больше нравится третий вариант:

using System;
using System.IO;
using System.Net;
using System.Text.RegularExpressions;
using System.Web;

class Program
{
    static void Main(string[] args)
    {
        try
        {
            TestArguments(args);
            WebRequest request = 
                   CreateWebRequest("http://www.comeaucomputing.com/pcgi-bin/compiler.cgi");
            WritePostFromFile(args[0], "Tused=-tused&Strict=-A&Version=433&Comment=", request);
            TransformResponseToWriter(request, Console.Out);
        }
        catch (Exception e)
        {
            Console.WriteLine(e.Message);
        }
    }

    private static void TestArguments(string[] args)
    {
        if (args.Length != 1)
            throw new Exception("Syntax: comoc filename");
    }

    private static void TransformResponseToWriter(WebRequest request, TextWriter writer)
    {
        using (StreamReader responseReader =
                new StreamReader(request.GetResponse().GetResponseStream()))
        {
            HttpUtility.HtmlDecode(new Regex("<pre>([^<]*)</pre>")
                .Match(responseReader.ReadToEnd()).Groups[1].Value, writer);
        }
    }

    private static void WritePostFromFile(string fileName, string prefix, WebRequest request)
    {
        request.Method = "POST";
        using (StreamWriter requestWriter = new StreamWriter(request.GetRequestStream()))
        {
            requestWriter.Write(prefix);
            using (StreamReader sourceTextReader = new StreamReader(fileName))
                requestWriter.Write(HttpUtility.UrlEncode(sourceTextReader.ReadToEnd()));
        }
    }

    private static WebRequest CreateWebRequest(string url)
    {
        WebRequest request = WebRequest.Create(url);
        return request;
    }
}

2 минуты обдумывания, и одна минута рефакторинга.

Твои варианты оба удовлетворительны. Это не настолько сложная функция чтобы понять что она делает. Но первый вариант, более понятен. Не мозолят глаза локальные переменные, и не надо в тексте выискивать что из них, что обозначает.
Насколько я помню (давно читал), изымать лишние локальные переменные описывалось правилом у Фаулера в Рефакторинге
Автор(ы): Мартин Фаулер, Кент Бек, Джон Брант, Дон Робертс, Уильям Апдайк

К тому времени как объектная технология — в частности язык Java — стала обычным
делом, появилось большое количество плохо спроектированных, неэффективных и
малопригодных к сопровождению и расширению приложений. Профессиональные
разработчики программных систем все яснее видят, насколько трудно иметь дело с
таким "неоптимальным" наследием. Уже несколько лет эксперты в области объектного
программирования применяют расширяющийся набор приемов, призванных улучшить
структурную целостность и производительность таких программ. Этот подход,
называемый рефакторингом, до сего момента оставался территорией экспертов,
поскольку не предпринималось попыток перевести профессиональные знания в форму,
доступную всем разработчикам.В данной книге Мартин Фаулер показывает,
как разработчики программного обеспечения могут реализовать существенные выгоды
этой новой технологии, где обычно лежат возможности изменения структуры и как
приступить к переделке плохого проекта в хороший. Каждый шаг рефакторинга прост
— на первый взгляд слишком прост, чтобы сделать его. Это может быть перемещение
поля из одного класса в другой, вынесение какого-то кода из метода и превращение
его в самостоятельный метод или даже перемещение кода по иерархии классов.
Каждый отдельный шаг может показаться элементарным, но совокупный эффект таких
малых изменений в состоянии радикально улучшить проект. Рефакторинг является
верным способом предотвращения распада программы. Помимо описания различных
приемов автор предоставляет подробный каталог, включающий более семидесяти
рефакторингов, а также полезные указания по их применению, пошаговые инструкции
и практические примеры. Примеры написаны на Java, но идеи применимы к любому
объектно-ориентированному языку программирования.
, и наличие излишних переменных считалось плохим кодом(с чем я соглашусь).
Re[3]: laconic vs. verbose
От: VladD2 Российская Империя www.nemerle.org
Дата: 18.05.06 20:52
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>А с чем несогласился Влад? Я задал какой-то религиозно неправильный вопрос, что-ли Зачем давать?


Имена переменных (если они не "a" или "b") являются частью документирования кода. Они побъясняют, что происходит. Ведь совсем не факт "http://.../compiler.cgi" — это URI, а не URL, а то и вообще черт знает что.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
Re[4]: laconic vs. verbose
От: Кодёнок  
Дата: 19.05.06 03:52
Оценка:
Здравствуйте, VladD2, Вы писали:

VD>Имена переменных (если они не "a" или "b") являются частью документирования кода. Они побъясняют, что происходит.


А если и так ясно, что происходит, то все равно нужно всегда, или иногда можно не делать? Я имею ввиду, например, в таком коде:
if (request.Headers.ContentType == "multipart/mixed")

тоже нужно константу сделать?

VD>Ведь совсем не факт "http://.../compiler.cgi" — это URI, а не URL, а то и вообще черт знает что.


Ок, у нас есть вызов стандартной функции System.Net.WebRequest.Create. Почему в данной программе важно подчеркнуть, что аргумент — это URI, что это дает, и чем опасно, если это не подчеркнуть?
Re[5]: laconic vs. verbose
От: WolfHound  
Дата: 19.05.06 11:07
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>А если и так ясно, что происходит, то все равно нужно всегда, или иногда можно не делать? Я имею ввиду, например, в таком коде:

Кё>
if (request.Headers.ContentType == "multipart/mixed")

Кё>тоже нужно константу сделать?
Обязательно. В строковом литееале можно шибится (особенно если он находится в нескольких местах) и никто тебе об этом не скажет (разве что ошибка во время исполнения которая может появится у клиента). А вот ошибится в имени константы тебе не даст компилятор. К тому же с константами работает интелисенс. Конечно можно ошибиться и при создании константы но засечь и исправить это гораздо легче чем работать напрямую со строковыми литералами.
... << RSDN@Home 1.1.4 beta 6a rev. 436>>
Пусть это будет просто:
просто, как только можно,
но не проще.
(C) А. Эйнштейн
Re[5]: laconic vs. verbose
От: VladD2 Российская Империя www.nemerle.org
Дата: 19.05.06 21:56
Оценка:
Здравствуйте, Кодёнок, Вы писали:

Кё>А если и так ясно, что происходит,


Если очень ясно, то можно забить. Догм делать из этого не стоит. Но чаще получается так, что забивают от лени.
... << RSDN@Home 1.2.0 alpha rev. 637>>
Есть логика намерений и логика обстоятельств, последняя всегда сильнее.
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.