С автоматизацией по жизни

Автор: Дмитрий Моисеев

Должность: ведущий программист

26.10.18

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

Я ведущий программист в компании Март. И в силу специфики работы, приходится постоянно думать об автоматизации. Нередко это выходит за рамки профессии и врывается в повседневную и даже личную жизнь. На выходных я помогал переносить дрова в частном доме. Машину колотых дров свалили около дороги, а во дворе есть дровник (сарай для дров), куда их нужно перетащить и аккуратно сложить. Задача не весть какая сложная, но долгая. И появилась мысль посчитать: “А сколько всего дров и когда мы закончим работу?” Ответить на этот вопрос я решил в свойственной мне, программистской манере…

Исходные данные. Работаем мы вчетвером - два человека складывают дрова в сарае для дров, два перевозят. Перевозили дрова на двух тачках. Весь процесс для меня выглядит следующим образом: подъехал с тачкой к куче дров, нагрузил дров в тачку, перевез тачку до дровника, выгрузил, поехал к куче дров и т.д. Для тех, кто складывает, все еще проще: тебе привезли дрова, выгрузили под ноги, а ты взял полено, положил, взял, положил… Разложив процесс на составные части, получаем данные, чтобы начать проектировать систему. Краткое о важном. 

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

Возвращаемся к исходному вопросу - сколько дров всего? Если сделать класс “КучаДров” - то у него был бы метод “сколькоВсегоДров()”, возвращающий общее количество, т.к. куча точно знает сколько в ней содержится дров. На практике она не умеет разговаривать, да и посчитать содержимое тоже вряд ли сможет. Но даже если попробовать реализовать этот метод, придется совершать дополнительную работу и пересчитывать все дрова вручную. Но постойте: мы же их перевозим, а значит и так перекладываем по 1 штуке, следовательно можно их посчитать. Чтобы это сделать - нужна система, автоматизирующая перевозку, способная вести учет и в конце перевозки ответить на вопрос - сколько же дров было.

Первое, что приходит на ум, при проектировании такой системы - определить классы-сущности в нашей системе. Понятно, что есть перевозчик (т.е. я), тачка, куча дров, место погрузки, место выгрузки и т.д. У сущностей есть параметры. Например, моя тачка была 2-х колесная, а вторая - с одним колесом. Моя более вместительная, да и из-за отличий в форме корыта складывать в ней дрова приходится чуть-чуть по-другому. И получается первый вариант декомпозиции (для тех, кто не очень хорошо понимает UML-диаграммы, буду писать на русском, а кому интересно узнать подробней - почитайте статью на википедии).

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

 

Дальше нужно описать клиентский код - т.е. тот, с которым будут работать пользователи системы и который будет использовать наши классы. Чтобы его расписать, нужно понять - как мы собираемся использовать систему? Какие есть сценарии использования (кому интересно почитать подробней - это называется use case)? Задач у нас несколько:

  1. Перевезти все дрова
  2. Подсчитать общее количество дров в куче

Алгоритм перевозки дров примерно следующий: 

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

Несмотря на то, что код написан на php, он должен быть достаточно понятен. Но в нем есть несколько спорных мест. Сомнительные функции “подвезтиТачкуККуче”, “перевезтиКМестуРазгрузки”, “положитьПолено” - все они непонятно кем и как должны выполняться, явно не хватает еще какого-то класса. Кроме того, не хватает методов проверки, которые используются в коде: не опустела ли куча, не наполнилась/опустела ли тачка? Ну и не решен главный вопрос - как посчитать общее количество?

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

 

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

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

 

Если вы думаете схожим образом и вам было все понятно и логично - милости просим к нам на работу! Нам нужны программисты, способные декомпозировать и решать задачи. Резюме можно отправить на job.mart.ru и мы с вами свяжемся.

P.s.: перенесли “машину” дров, сколько бы их там в штуках ни было.