Рубрики
Без рубрики

Как завершить проект по программированию с нуля

В настоящее время я в своем последнем семестре преподаю курс программирования второго курса по программному компоненту… С тегами java, новички, программирование, информатика.

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

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

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

Обзор проекта

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

Например, для 4-го проекта мы просим студентов создать программу чтения RSS, которая отображает RSS-канал в виде веб-страницы HTML. Вместо того, чтобы просить их сделать это с нуля, мы предоставляем 5 пустых методов с подробными контрактами. Все, что нужно сделать студентам, это заполнить методы, и у них будет работающий RSS-ридер.

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

  • Приглашение для ввода файла терминов и определений, а также имени папки для выходных файлов
  • Индексный файл, содержащий все термины, расположен в алфавитном порядке
  • Серия страниц терминов, которые содержат определения слов, а также ссылки на другие термины в определениях

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

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

Как начать работу

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

Ладно, это не совсем так . На самом деле мы их совсем немного готовим, но они не всегда осознают это. По мере приближения к заданию по глоссарию мы просим наших студентов внедрять методы, которые могут быть полезны в проекте во время лабораторных работ — мы просто прямо не говорим им об их ценности. Идея состоит в том, чтобы они помнили, что реализовали что-то, что могло бы быть полезным. К сожалению, они не всегда устанавливают такую связь.

В любом случае, мы неизбежно заваливаемся всевозможными просьбами студентов о помощи. На самом деле, на прошлой неделе я получил несколько электронных писем со всевозможными вопросами. Написав довольно длинное электронное письмо студенту, я решил, что могу развернуться и превратить некоторые из своих советов в официальное объявление. Затем я подумал: “Почему бы мне просто не написать статью, которая могла бы помочь еще большему количеству людей?” Так я и сделал.

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

Задавайте Уточняющие Вопросы

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

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

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

Никто не ожидает, что мы будем точно знать то, чего мы не знаем.

Перечислите Задачи

Не знаете, что делать? Составьте список задач.

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

  • Приглашение для ввода файла терминов и определений, а также имени папки для выходных файлов
  • Индексный файл, содержащий все термины в алфавитном порядке
  • Серия страниц терминов, которые содержат определения слов, а также ссылки на другие термины в определениях

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

Если мы будем думать о методах как о задачах, мы будем на верном пути к завершению проекта.

Отображение Потока Данных Через Задачи

Соединяйте задачи с данными.

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

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

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

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

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

Определение Интерфейсов Задач

На этом этапе основная часть “размышлений” завершена. Теперь мы можем приступить к созданию вашего собственного шаблона. Для этого нам нужно будет определить интерфейсы для наших методов. Давайте начнем с описания наших трех методов без каких-либо входов или выходов:

public static ... readTermsAndDefinitions( ... ) { ... }
public static ... generateIndexPage( ... ) { ... }
public static ... generateTermPages( ... ) { ... }

Описав эти методы в общих чертах, мы можем начать думать о том, что каждый из них будет делать. Во-первых, метод чтения терминов и определений() будет анализировать входной файл и преобразовывать его в древовидную карту. Другими словами, он, вероятно, должен взять сканер и вернуть древовидную карту:

public static TreeMap readTermsAndDefinitions(Scanner input) { ... }

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

public static void generateIndexPage(TreeMap termsAndDefs) { ... }
public static void generateTermPages(TreeMap termsAndDefs) { ... }

Теперь мы сделали несколько довольно серьезных предположений с помощью этих методов. Во-первых, мы предположили, что все имена файлов могут быть выведены из параметра термины и Определения . Например, мы могли бы назвать каждую страницу термина после термина (например car.html , bat.html и т.д.). Аналогичным образом, предполагалось, что индексная страница будет index.html .

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

А пока давайте двигаться дальше.

Как заполнить шаблон

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

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

Разбивайте Задачи на Подзадачи

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

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

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

труд::работа, особенно тяжелая физическая работа.

усилие::попытка достичь цели.

предприятие::проект или предприятие, как правило, сложное или требующее усилий.

Здесь каждый термин и определение напечатаны на отдельной строке. Затем термин отделяется от определения двойным двоеточием.

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

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

Тестовое Поведение, А Не Реализация

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

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

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

В нашем случае мы должны писать тесты только для наших трех методов на уровне задач: чтение терминов и определений() , generateIndexPage() и generateTermpAges() . Идея здесь в том, что затем мы можем изменить все, что происходит под капотом, без необходимости переписывать наш тестовый код; он просто будет работать бесконечно.

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

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

Польский и настоящий

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

Как и в большинстве случаев в жизни, завершение проекта следует правилу 80/20. Другими словами, 80% нашего времени будет потрачено на доработку последних 20% проекта. Как только мы установим основную часть функциональности, мы потратим оставшуюся часть нашего времени на то, чтобы убедиться, что все находится в идеальном рабочем состоянии.

В подобном проекте последние 20% будут приходиться на следующие типы задач:

  • Исправление крайних случаев бизнес-логики
  • Изменение стиля вывода HTML-кода
  • Форматирование текста для подсказок ввода
  • Генерация тестовых данных
  • Рефакторинг базовой структуры метода
  • Настройка производительности
  • Документирование кода

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

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

Дополнительные советы

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

Конечно, все эти инструменты очень важны. На самом деле, я бы сказал, что каждый программный проект должен, по крайней мере, контролироваться версиями. К счастью, программное обеспечение для управления версиями широко поддерживается сообществом, и большинство людей знакомы с популярными центрами управления версиями, такими как BitBucket, GitHub и GitLab. Если вы заинтересованы в том, чтобы начать создавать свой первый репозиторий, у меня есть краткое руководство, в котором используются Git и GitHub .

В дополнение к контролю версий может быть полезно использовать некоторую технологию непрерывной интеграции (CI). Лично мне нравится Travis CI, потому что он напрямую интегрируется в GitHub, но существует множество инструментов CI. Например, я думаю, что самый популярный инструмент – это Дженкинс. При правильной настройке эти инструменты можно использовать для тестирования кода каждый раз, когда происходит фиксация. Затем, когда проект будет готов к запуску, эти инструменты также могут развернуть все решение от вашего имени.

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

Поделитесь Своими Советами

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

Что насчет тебя? Как вы подходите к совершенно новому проекту? Вы просто погружаетесь или немного планируете? Существуют ли какие-либо инструменты, которые вы используете для оказания помощи в процессе разработки? Вы работаете в команде или предпочитаете действовать в одиночку? Какова ваша общая стратегия рефакторинга кода? И как вы планируете использовать дополнительные функции после того, как проект будет “завершен”?

Разработка программного обеспечения – это запутанный процесс, и мы еще не полностью разработали отличные процессы выполнения работы. Часть меня думает, что это потому, что мы относимся к разработке программного обеспечения как к сложной науке, хотя зачастую это скорее творческое искусство. Другими словами, проекты растут и органично меняются с течением времени, и не всегда ясно, чем закончится проект. Как нам сбалансировать реальность перемен с желанием наметить все возможные сценарии?

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

Наконец, если вам понравилась эта статья, вот несколько отобранных статей для вас:

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

Сообщение Как завершить проект по программированию с нуля появилось первым на Программист-отступник .

Оригинал: “https://dev.to/renegadecoder94/how-to-complete-a-programming-project-from-scratch-2keh”