Руководства по кодированию: как вы разделяете свои большие исходные файлы? - PullRequest
7 голосов
/ 04 марта 2009

Проект, над которым я работаю, только что набрал 4200 строк в основном файле C #, что заставляет IntelliSense реагировать в течение нескольких секунд (иногда до 6 или около того), в течение которых Visual Studio блокируется. Мне интересно, как все остальные делят свои файлы и есть ли консенсус.

Я попытался найти несколько руководств и нашел Руководство по Google C ++ , но я ничего не увидел в семантике, такой как размеры функций и размеры файлов; может быть, это там - я давно не смотрел на это.

Так как же вы разделяете файлы? Вы группируете свои методы по функциям, которые они выполняют? По типам (обработчики событий, частные / публичные)? И при каком размере вы разделяете функции?

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

Ответы [ 14 ]

19 голосов
/ 04 марта 2009

Я думаю, что ваша проблема суммируется с тем термином, который вы используете: "Основной файл C #".

Если вы не имеете в виду main (как в методе main ()), для этой концепции нет места.

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

Как правило, мои файлы представляют собой сопоставления классов один к одному.

Иногда очень связанные классы находятся в одном файле.

Если ваш файл слишком большой, это говорит о том, что ваш класс слишком большой и слишком общий.

Я стараюсь, чтобы мои методы не превышали половины экрана. (Когда это код, который я пишу с нуля, он обычно составляет 12 строк или меньше, но в последнее время я работал над существующим кодом от других разработчиков, и мне пришлось реорганизовать 100 строковых функций ...)

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

EDIT:

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

15 голосов
/ 07 марта 2009

В классической книге " Структурное программирование " Дейкстра однажды написал раздел под названием: "О нашей неспособности сделать многое". Его точка зрения была проста. Люди не очень умные. Мы не можем совмещать в уме несколько концепций одновременно.

Очень важно, чтобы ваши классы и методы были небольшими. Когда метод превышает дюжину строк или около того, он должен быть разбит на части. Когда класс становится выше пары сотен строк, он должен быть разбит на части. Это единственный способ сохранить код хорошо организованным и управляемым. Я программирую почти 40 лет, и с каждым годом я понимаю, насколько важно слово «маленький» при написании программного обеспечения.

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

14 голосов
/ 04 марта 2009

Разделите ваши типы, где это естественно, чтобы разделить их - но остерегайтесь типов, которые делают слишком много. Около 500 строк (на Java или C #) меня беспокоит. Примерно с 1000 строк я начинаю задумываться о том, должен ли тип разбиваться ... но иногда этого просто не может / не должно быть.

Что касается методов: мне не нравится, когда я не вижу весь метод на экране одновременно. Очевидно, что это зависит от размера монитора и т. Д., Но это разумное правило. Я предпочитаю, чтобы они были короче, хотя. Опять же, есть исключения - некоторую логику действительно трудно распутать, особенно если есть много локальных переменных, которые естественно не хотят объединяться вместе.

Иногда имеет смысл иметь для одного типа лот методов - таких как System.Linq.Enumerable, но частичные классы могут помочь в таких случаях, если вы можете разбить тип до логических групп (в случае Enumerable группировка по операциям агрегации / задания / фильтрации и т. д. выглядела бы естественной). Однако в моем опыте такие случаи редки.

5 голосов
/ 04 марта 2009

Книга Мартина Фаулера Рефакторинг Я думаю, дает вам хорошую отправную точку для этого. В нем рассказывается, как определить «запахи кода» и как изменить код, чтобы устранить эти «запахи». Естественный результат (хотя это и не является основной целью) состоит в том, что в результате вы получаете меньшие, более обслуживаемые классы.

EDIT

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

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

4 голосов
/ 04 марта 2009

Не кодируйте процедурно, и вы не получите 4200 строк в одном файле.

В C # хорошая идея придерживаться некоторых SOLID принципов объектно-ориентированного проектирования. У каждого класса должна быть одна-единственная причина для изменения. Основной метод должен просто запустить начальную точку приложения (и сконфигурировать ваш контейнер внедрения зависимостей, если вы используете что-то вроде StructureMap).

У меня обычно нет файлов с более чем 200 строками кода, и я предпочитаю их, если они меньше 100.

3 голосов
/ 04 марта 2009

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

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

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

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

Вы должны прочитать о стиле C # и рефакторинг, чтобы действительно понять проблемы, которые вы решаете.

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

Элементы стиля C # - это хорошее руководство по стилю мертвого дерева в C #, а в этом блоге есть несколько ссылок на хорошие руководства по стилю в Интернете.

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

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

2 голосов
/ 04 марта 2009

Каждый класс должен делать одну маленькую вещь и делать это хорошо. Ваш класс - Форма? Тогда в нем не должно быть ЛЮБОЙ бизнес-логики.

Представляет ли это одну концепцию, например, пользователя или государство? Тогда он не должен иметь никакого рисунка, загрузки / сохранения и т.д ...

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

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

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

Позвольте мне найти хороший пост ... Просмотрите их, чтобы начать:

как-д-я-брейк-мой-процедурное кодирование-привычка

есть-там любой-правила для-упа

объектно-ориентированный передовой практика, наследование-v-композиционный-V-интерфейсы

Есть также посты, в которых вы найдете ссылки на хорошие книги по дизайну ОО. Книга «Рефакторинг» - это, пожалуй, одно из лучших мест, которое вы могли бы начать.

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

Удачи.

1 голос
/ 04 марта 2009

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

  • Все ли методы используются только в этом классе? Ищите вспомогательные методы, такие как проверка, манипулирование строками, которые можно переместить в классы помощника / утилит.

  • Вы используете какие-либо разделы #region? Логические группировки связанных методов в #region часто подразделяются на отдельные классы.

  • Является ли класс формой? Рассмотрите возможность использования пользовательских элементов управления для элементов управления форм или групп элементов управления.

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

1 голос
/ 04 марта 2009

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

Есть очень веские причины для разделения файлов классов на более мелкие файлы (и не менее веские причины для перемещения файлов в разные проекты / сборки).

Подумайте, какой цели должен достичь ваш класс. Каждый файл должен иметь только одну цель. Если он слишком обобщен в своей цели, например, «Содержать логику корзины покупок», то вы идете по неверному пути.

Также, как уже упоминалось, используемый вами термин: «Основной файл C #» просто пахнет тем, что у вас очень процедурный склад ума. Я бы посоветовал остановиться, сделать шаг назад и быстро прочитать некоторые из следующих тем:

  • Общие принципы ООП
  • Домен-управляемый дизайн
  • Модульное тестирование
  • IoC Контейнеры

Удачи в ваших поисках.

0 голосов
/ 07 марта 2009

Разделите код так, чтобы каждый класс / файл / функция / и т. Д. делает только одну вещь ™. Принцип единой ответственности является хорошим руководством для разделения функциональности на классы.

В настоящее время самые большие классы, которые я пишу, имеют длину около 200 строк, а методы - в основном 1-10 строк.

...