2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




Начать новую тему Ответить на тему На страницу 1, 2, 3, 4, 5, 6  След.
 
 Сравнение двух стилей программирования
Сообщение12.12.2012, 20:26 
Аватара пользователя


15/01/12
87
г. Москва
Всем доброго времени суток.

Краткая предыстория.
Я помаленьку увлекаюсь программированием уже много лет, с разной интенсивностью.
Соответственно как-то уже выработал привычки по написанию хорошего кода.
А в этом году поступил в крупный технический ВУЗ, на "CS"-специальность.
И столкнулся с массой людей, которые код пишут первый раз и потому пишут его "как могут".
Что заставило меня несколько задуматься о том, насколько ценны те принципы, которые я соблюдаю, уже на задумываясь об их смысле.

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

Мой:
код: [ скачать ] [ спрятать ]
Используется синтаксис Delphi
program list1;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type
  pe=^element;
  element=record
    value: integer;
    next: pe;
  end;

var first, last, q: pe;
    x: integer;

procedure add(x: integer; var last: pe);
var t: pe;
begin
  New(t);

  t^.value:=x;
  t^.next:=nil;
  last^.next:=t;

  last:=t;
end;

procedure clear(var first: pe);
var t: pe;
begin
  while first<>nil do
    begin
      t:=first;
      first:=first^.next;
      Dispose(t);
    end;
end;

begin

  WriteLn('Input numbers:');
  ReadLn(x);

  New(first);
  first^.value:=x;
  first^.next:=nil;
  last:=first;

  ReadLn(x);
  while x<>0 do
    begin
      add(x, last);
      ReadLn(x);
    end;

  q:=first;
  while q<>nil do
   begin
    Write(q^.value, ' ');
    q:=q^.next;
   end;

  ReadLn;
  clear(first);

end.
 


Не мой:
код: [ скачать ] [ спрятать ]
Используется синтаксис Delphi
program list_zl;

{$APPTYPE CONSOLE}

uses
  SysUtils;

type pe=^element;
     element=record
      value: integer;
      next: pe;
     end;

var
    first,last,q,t: pe;
    x: integer;

begin
  writeln('Input numbers:');
  ReadLn(x);

  New(first);
  first^.value:=x;
  last:=first;

  ReadLn(x);
  while x<>0 do
    begin
      New(last^.next);
      last:=last^.next;
      last^.value:=x;

      ReadLn(x);
    end;
  last^.next:=nil;

  q:=first;
  while q<>nil do
    begin
      write(q^.value,' ');
      t:=q;
      q:=q^.next;
      dispose(t);
    end;

 ReadLn;

end.
 


Второй почти в полтора раза короче. :\
Думаю, разницу в организации кода объяснять не надо, всё очевидно.

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

 Профиль  
                  
 
 Re: Сравнение двух стилей программирования
Сообщение12.12.2012, 22:09 
Заслуженный участник


28/04/09
1933
Для выполнения учебных задач вполне хватит и второго. Однако при написании более-менее больших программ лучше пользоваться первым (по целому ряду причин). А выработать навыки написания хорошо структурированного кода можно при выполнении учебных задач. :D
Однако Вы остановились зачем-то на полпути. Код можно сделать еще вдвое длиннее и на порядок структурированнее (прошу прощения за возможные ошибки, на Pascal не писал уже очень давно, проверить работоспособность кода не могу):
код: [ скачать ] [ спрятать ]
Используется синтаксис Delphi
program ListOperations;

{$APPTYPE CONSOLE}

uses
        SysUtils;

type

        PElement = ^TElement;
       
        TElement =
                record
                        value : Integer;
                        nextElement : PElement;
                end;
               
        TList =
                record
                        firstElement : PElement;
                        lastElement : PElement;
                end;

var
        list : TList;


procedure InitList(var list : TList);
begin
        list.firstElement = nil;
        list.lastElement = nil;
end;

procedure AddElement(var list : TList; value : Integer);
var
        newElement : PElement;
begin
        New(newElement);
        newElement^.value := value;
        newElement^.nextElement := nil;
        with list do
        begin
                if firstElement = nil then
                        firstElement := newElement
                else
                        lastElement^.nextElement := newElement;
                lastElement := newElement;
        end;
end;

procedure ReadList(var list : TList);
var
        value : Integer;
begin
        WriteLn('Input list elements:');
        ReadLn(value);
        while value <> 0 do
        begin
                AddElement(list, value);
                ReadLn(value);
        end;
end;

procedure WriteList(const list : TList);
var
        element : PElement;
begin
        Writeln('List elements:');
        element := list.firstElement;
        while element <> nil do
        begin
                Write(element^.value, ' ');
                element := element^.nextElement;
        end;
        Writeln;
end;

procedure ClearList(var list : TList);
var
        element : PElement;
begin
        with list do
        begin
                while firstElement <> nil do
                begin
                        element := firstElement;
                        firstElement := firstElement^.nextElement;
                        Dispose(element);
                end;
                lastElement = nil;
        end;
end;

begin
        InitList(list);
        ReadList(list);
        WriteList(list);
        ReadLn;
        ClearList(list);
end.

 Профиль  
                  
 
 Re: Сравнение двух стилей программирования
Сообщение12.12.2012, 22:54 
Аватара пользователя


15/01/12
87
г. Москва
Впечатлён. Ошибок, кстати, почти нет, только в трёх местах "=" вместо ":=".
Скажите, Вы профессиональный программист? (:

(Оффтоп)

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

 Профиль  
                  
 
 Re: Сравнение двух стилей программирования
Сообщение12.12.2012, 23:09 
Заслуженный участник


28/04/09
1933
shau-kote в сообщении #657741 писал(а):
Ошибок, кстати, почти нет, только в трёх местах "=" вместо ":=".
Хорошо хоть == на = в условии успел поменять.
shau-kote в сообщении #657741 писал(а):
Скажите, Вы профессиональный программист? (:
Раз ошибки есть, значит непрофессиональный. :-)
shau-kote в сообщении #657741 писал(а):
Это же создаст условие, которое будет проверяться каждый раз при выполнении тела цикла, но выполнится только единожды, что не круто.
В целом нехорошо, но и анализировать производительность до появления проблем с нею не слишком хорошо (по крайней мере, в такого рода программах). В данном случае выполнение единственного лишнего оператора рядом с заведомо более долгой операцией ввода не скажется на ней никак.
А уж предыдущий вариант, когда введенный первым ноль попадал в список вопреки всякой логике, заведомо хуже, поскольку вводит и пользователей программы, и пользователей кода в ненужные заблуждения.

 Профиль  
                  
 
 Re: Сравнение двух стилей программирования
Сообщение12.12.2012, 23:20 
Аватара пользователя


15/01/12
87
г. Москва
EtCetera в сообщении #657753 писал(а):
А уж предыдущий вариант, когда введенный первым ноль попадал в список вопреки всякой логике, заведомо хуже, поскольку вводит и пользователей программы, и пользователей кода в ненужные заблуждения.

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

 Профиль  
                  
 
 Re: Сравнение двух стилей программирования
Сообщение12.12.2012, 23:37 
Заслуженный участник
Аватара пользователя


30/01/06
72407

(Оффтоп)

А в procedure add никто не хочет last^.next на nil проверить? А то в чём смысл структурировать программу, если получающиеся куски всё равно полагаются друг на друга...

 Профиль  
                  
 
 Re: Сравнение двух стилей программирования
Сообщение12.12.2012, 23:55 
Аватара пользователя


15/01/12
87
г. Москва

(Оффтоп)

Нет, не хочу. (:
Потому что можно очень много чего проверять. Добавить ещё возвращение кода ошибки.
А можно просто полагать, что программист передаёт подпрограмме корректные данные.
В противном случае он ССЗБ, как говорится.

 Профиль  
                  
 
 Re: Сравнение двух стилей программирования
Сообщение13.12.2012, 00:16 
Заслуженный участник


09/09/10
3729

(Оффтоп)

Барьерный элемент всандалить в конец, и все, можно уже STL-подобный iterator делать.

shau-kote в сообщении #657777 писал(а):
А можно просто полагать, что программист передаёт подпрограмме корректные данные.
В противном случае он ССЗБ, как говорится.

О, я встречался с одной библиотекой, которая никак не валидировала входные параметры — впечатления очень не очень.

 Профиль  
                  
 
 Re: Сравнение двух стилей программирования
Сообщение13.12.2012, 00:38 
Заслуженный участник
Аватара пользователя


30/01/06
72407

(Оффтоп)

shau-kote в сообщении #657777 писал(а):
Потому что можно очень много чего проверять.

В идеале да. А тут всего лишь precondition процедуры, такой весь из себя очевидный и единственный.

shau-kote в сообщении #657777 писал(а):
А можно просто полагать, что программист передаёт подпрограмме корректные данные.

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

 Профиль  
                  
 
 Re: Сравнение двух стилей программирования
Сообщение13.12.2012, 00:53 
Аватара пользователя


15/01/12
87
г. Москва

(Оффтоп)

Хорошо, что вы предлагаете делать, если last^.next<>nil?
А если недостаточно памяти для создания нового элемента? Тоже, в общем-то, precondition процедуры.
А если число, переданное в процедуру, нельзя без потерь преобразовать к типу value?

 Профиль  
                  
 
 Re: Сравнение двух стилей программирования
Сообщение13.12.2012, 01:11 
Заслуженный участник


04/05/09
4587
shau-kote в сообщении #657789 писал(а):
Хорошо, что вы предлагаете делать, если last^.next<>nil?
Вставлять в середину списка.
shau-kote в сообщении #657789 писал(а):
А если недостаточно памяти для создания нового элемента?
Возвращать ошибку наиболее подходящим способом, я не помню, как в Паскале принято.
shau-kote в сообщении #657789 писал(а):
А если число, переданное в процедуру, нельзя без потерь преобразовать к типу value?
Так ведь у вас аргумент уже соответствующего типа.

 Профиль  
                  
 
 Re: Сравнение двух стилей программирования
Сообщение13.12.2012, 01:28 
Аватара пользователя


15/01/12
87
г. Москва
venco в сообщении #657791 писал(а):
Вставлять в середину списка.

Хм. Ну, хорошо, согласен.
Хотя, учитывая, что первоначальная логика работы процедуры была "добавить элемент в конец списка", я бы предпочёл, чтобы она вернула ошибку.

venco в сообщении #657791 писал(а):
Возвращать ошибку наиболее подходящим способом, я не помню, как в Паскале принято.

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

venco в сообщении #657791 писал(а):
Так ведь у вас аргумент уже соответствующего типа.

Да, но с учётом довольно слабой типизации Pascal'я, ничто не помешает передать в процедуру какой-нибудь longint, значение в котором ну никак не будет помещаться в поле value типа integer.
Что, однако, не помешает программу его туда засунуть. С плачевным результатом, само собой.

 Профиль  
                  
 
 Re: Сравнение двух стилей программирования
Сообщение13.12.2012, 02:15 
Заслуженный участник


04/05/09
4587
shau-kote в сообщении #657794 писал(а):
venco в сообщении #657791 писал(а):
Так ведь у вас аргумент уже соответствующего типа.

Да, но с учётом довольно слабой типизации Pascal'я, ничто не помешает передать в процедуру какой-нибудь longint, значение в котором ну никак не будет помещаться в поле value типа integer.
Что, однако, не помешает программу его туда засунуть. С плачевным результатом, само собой.
Это уже проблема вызывающего кода. Функция AddElement() принимает Integer, и всё.

-- Ср дек 12, 2012 18:19:14 --

shau-kote в сообщении #657794 писал(а):
venco в сообщении #657791 писал(а):
Вставлять в середину списка.

Хм. Ну, хорошо, согласен.
Хотя, учитывая, что первоначальная логика работы процедуры была "добавить элемент в конец списка", я бы предпочёл, чтобы она вернула ошибку.
Если уж так хочется именно в конец, то надо бы пробежать до этого конца, и вставить там.

-- Ср дек 12, 2012 18:25:57 --

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

 Профиль  
                  
 
 Re: Сравнение двух стилей программирования
Сообщение13.12.2012, 02:45 
Аватара пользователя


15/01/12
87
г. Москва
venco в сообщении #657796 писал(а):
Это уже проблема вызывающего кода. Функция AddElement() принимает Integer, и всё.

Так, пардоньте, и то, что last не является указателем на последний элемент списка, проблема вызывающего кода, а не процедуры.
Процедура add(как и AddElement) принимает указатель на последний элемент и всё. (:

venco в сообщении #657796 писал(а):
Как вы уже поняли, если писать в первом стиле - типа библиотеку с возможностью повторного использования, то надо тщательнее подходить к разработке как интерфейса, так и имплементации. А скорее всего, такая библиотека уже есть, и лучше использовать уже готовое.
Если же код пишется на один раз, то проще, да и короче, писать во втором стиле, зная какие есть пре- и пост- условия на месте, и пользуясь этим.

А вот это особо интересно.
Понятно, что задача реализации библиотеки - это отдельная задача, со своими тонкостями, тут и разработка гибкого интерфейса и прочая, прочая, прочая.
Но Вы считаете, что в контексте небольшой конечной задачи мой подход (или, допустим, подход EtCetera) не слишком целесообразен?
А как же логическое структурирование кода? Упрощение отладки? Повышение гибкости программы? Удобство дальнейшей модификации?

 Профиль  
                  
 
 Re: Сравнение двух стилей программирования
Сообщение13.12.2012, 02:59 
Заслуженный участник


04/05/09
4587
shau-kote в сообщении #657800 писал(а):
venco в сообщении #657796 писал(а):
Это уже проблема вызывающего кода. Функция AddElement() принимает Integer, и всё.

Так, пардоньте, и то, что last не является указателем на последний элемент списка, проблема вызывающего кода, а не процедуры.
Процедура add(как и AddElement) принимает указатель на последний элемент и всё. (:
Какой именно элемент - не ясно, т.к. тип тот же. А вот не-Integer передать в AddElement() невозможно, что именно вы собираетесь проверять?

shau-kote в сообщении #657800 писал(а):
Повышение гибкости программы? Удобство дальнейшей модификации?
Это уже будет не одноразовый код. Разделение не по размеру, а по повторному использованию. Вы гораздо больше времени потеряете на раздумья, а такие ли аргументы я дал, а что будет, если параметры не те. В одноразовом коде они не могут быть не те.

 Профиль  
                  
Показать сообщения за:  Поле сортировки  
Начать новую тему Ответить на тему  [ Сообщений: 82 ]  На страницу 1, 2, 3, 4, 5, 6  След.

Модераторы: Karan, Toucan, PAV, maxal, Супермодераторы



Кто сейчас на конференции

Сейчас этот форум просматривают: нет зарегистрированных пользователей


Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете добавлять вложения

Найти:
Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group