К списку форумов К списку тем
Регистрация    Правила    Главная форума    Поиск   
Имя: Пароль:
Рекомендовать в новости

Красивый код

Гость
0 - 08.11.2014 - 21:34
Всех приветствую.
Я - админ с 12-летним стажем. Лет 10 назад писал на c++, делфи, даже ассемблере, но все успешно забыл. После этого писал только скрипты (perl, bash).
Решил выучать java. При чем, качественно выучить, со всеми бестпрактисами.
Пока читаю книгу по написанию "hello world", я параллельно практикуюсь - пишу программу, анализирующую состояние сервера (для aix, но это почти то же самое, что для linux).
И тут возник вопрос(собственно, постановка задачи):
я прочитал, что каждый метод должен помещаться на одном экране.
У меня есть метод "собрать информацию с сервера". Он читает разные конфиги, запускает программы и заносит различную информацию в различные переменные(которые будут проанализированы в другом методе).
Метод, мягко говоря, немаленький и я не понимаю, как правильно его уменьшить.
Естественно, все второстепенное (открыть файл, распарсить в соответствии со структурой, вынутьзначение) оформлено второстепенными приватными методами.
Логика метода весьма проста:
1. Получить список сетевых интерфейсов, запомнить их названия
2. Для каждого из сетевых интерфейсов получить их (список параметров) и запомнить
3. Получить список дисков
...

Подскажите пожалуйста, какие есть "способы" разделить метод на более маленькие? Или в этом нет ничего страшного?
Разделять "по контенту"(диски, сетевые адаптеры, ...) считаю не очень разумным: делаю ведь одно и то же.



Гость
1 - 09.11.2014 - 00:30
>Логика метода весьма проста:
>1. Получить список сетевых интерфейсов, запомнить их названия
>2. Для каждого из сетевых интерфейсов получить их (список параметров) и запомнить
>3. Получить список дисков
>...


очевидно, что самые простой вариант - объявить интерфейс подобный InfoProvider<T> ** void getInfo(Callback<T> receiver) **

который и дергать в "основном методе" а получение спсика интерфейсов и их параметров в один класс реализующий сей интерфейс, для дисков другой

причем там в каждом классе отдельно выделить получение списка интерфейсов, отдельно получение их параметров

просто потому что все это неплохо бы оттестировать, да и наверняка некоторые вещи будет неплохо кешировать
Гость
2 - 09.11.2014 - 01:08
Сферический совет в вакууме: если хочется лучших практик, почитайте за паттерны и рефакторинг. Фаулер, Банда четырёх там, Макконнелл, всякое такое. Но аккуратно, культа не делайте.
Гость
3 - 09.11.2014 - 11:19
0-Добрых дел мастер > Т.к. нет полной картины что делает этот чудо-метод, будем крутить коня в томате.

1. Познать ООП, потому что ты пытаешься писать на bash "словами" из java.

2. Разделять и властвовать: каждый твой пункт вынести запределы метода, любым приемленмым способом. см 1

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

4. Пиши камменты и тесты, поможет в 3

П.с. полезно смотреть код других проектов, github в помощь
Гость
4 - 09.11.2014 - 15:21
Цитата:
Сообщение от wayerr Посмотреть сообщение
очевидно, что самые простой вариант - объявить интерфейс подобный InfoProvider ** void getInfo(Callback receiver) ** который и дергать в "основном методе" а получение спсика интерфейсов и их параметров в один класс реализующий сей интерфейс, для дисков другой причем там в каждом классе отдельно выделить получение списка интерфейсов, отдельно получение их параметров
Главная проблема в том, что трудно провести границу между интерфейсами.
Например, изучив список файловых систем, хочется понять что за диски, может быть они находятся на внешней СХД, подключенной по iSCSI, что ведет нас к изучению сетевых адаптеров...
Цитата:
Сообщение от kowalski Посмотреть сообщение
почитайте за паттерны и рефакторинг. Фаулер, Банда четырёх там, Макконнелл, всякое такое.
Я пока-что не дочитал "Java: A Beginner's Guide". Дальше по плану - TDD. Паттерны и рефакторинг, насколько я понял, это уже на несколько уровней выше.
Метаться не хочется воизбежание каши в голове, но хочется хотя бы "не укоренять самые крупные ошибки". Поэтому прочитал пару статей по рефакторингу, но вопросов возникло больше, чем ответов.

Цитата:
Сообщение от 40KHYTbIU Посмотреть сообщение
Познать ООП, потому что ты пытаешься писать на bash "словами" из java.
Есть такое. Ну почти. Раньше я писал на c++ и делфи, так что слова class и try..catch мне знакомы.
Цитата:
Сообщение от 40KHYTbIU Посмотреть сообщение
3. Пиши бейби-код, так чтоб любой сторонний человек знающий java смог быстро понять о чем речь.
А что такое бейби-код? Гугл ничего не сказал.
Гость
5 - 09.11.2014 - 16:48
>Главная проблема в том, что трудно провести границу между интерфейсами.

это не проблема красоты кода, а проблема проектирования
Гость
6 - 09.11.2014 - 18:44
Рефакторинг... Скока раз порывался свой код улучшить, а то и переписать заново. Вынести нящки в классы, функции, развернуть свой git-реп итд. Став "нассяльника" - пытался заставить сделать это подчиненных. Короче... - это несбыточно. Работает - и фиг с ним. Не надо ничего уменьшать, ведь и художники бывают многословными...
Гость
7 - 09.11.2014 - 19:22
Цитата:
Сообщение от wayerr Посмотреть сообщение
это не проблема красоты кода, а проблема проектирования
а есть что-нибудь короткое, где описано, как правильно проектировать приложение? Нормальные книги я, конечно, прочту, но это будет позже.
Цитата:
Сообщение от economist Посмотреть сообщение
Короче... - это несбыточно. Работает - и фиг с ним. Не надо ничего уменьшать, ведь и художники бывают многословными...
Так речь не о рефакторинге, а о том, чтобы сразу учиться хорошему.
Гость
8 - 09.11.2014 - 21:01
>а есть что-нибудь короткое, где описано, как правильно проектировать приложение?

не встречал, можно почитать про базовые ошибки напр. тут https://ru.wikipedia.org/wiki/Антипа...8_.D0.9F.D0.9E но там все описано уже затейливое терминологогией
Гость
9 - 09.11.2014 - 21:20
> Скока раз порывался свой код улучшить, а то и переписать заново. Вынести нящки в классы, функции, развернуть свой git-реп итд. Став "нассяльника" - пытался заставить сделать это подчиненных.

ээ, да вам нужны Программисты, а не программисты, может даже тимлид просто нормальный который таки умеет рефакторить код, ведь это тривиально.
Гость
10 - 09.11.2014 - 21:55
6-economist >Плюсану, идеального кода нет. Если код работает годами и заказчик доволен работой, то это и есть идеальный код. И пофигу как там внутри. Потом, как часто бывает, заказали одно, потом резко под конец решили что-то поменять, а сроки оставили прежними. И вот какой тут будет идеальный код можете догадаться.
Гость
11 - 09.11.2014 - 23:11
>И пофигу как там внутри.

потому в краснодаре и нет софтверных контор, некоторые даже без VCS работают
Гость
12 - 09.11.2014 - 23:59
Цитата:
Сообщение от wayerr Посмотреть сообщение
не встречал, можно почитать про базовые ошибки напр. тут https://ru.wikipedia.org/wiki/Антипа...8_.D0.9F.D0.9E но там все описано уже затейливое терминологогией
Очень непонятно описано. Но ладно, поищу что-нибудь.
Цитата:
Сообщение от ipp Посмотреть сообщение
люсану, идеального кода нет. Если код работает годами и заказчик доволен работой, то это и есть идеальный код.
Как я писал выше, дело ведь не в результате, а в обучении. Наговнокодить я всегда успею, но хотя бы стремиться я должен к чему-то правильному.
Гость
13 - 10.11.2014 - 00:15
>Очень непонятно описано

ну я говорил про терминологию, кроме того там одно и тоже разными словами упоминается, и есть вещи верные только в контексте (а не всегда)

в случае :

>Логика метода весьма проста:
>1. Получить список сетевых интерфейсов, запомнить их названия
>2. Для каждого из сетевых интерфейсов получить их (список параметров) и запомнить
>3. Получить список дисков

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

так хороший код для того кто думает процедурами будет (вместо одного метода):

netdevs = get_networking_devices();
for(dev: netdevs) **
__attrr = get_netdevice_attrs(dev);
__save_attrs(dev, attrr)
**
strdevs = get_storage_devices();
for(dev: strdevs) **
__get_storage_attrs(dev);
**


школьники только постигшие ооп, напишут так


netdevs = NetDevsService.list();
for(dev: netdevs) **
__attrr = dev.getAttrs();
__PeristentService.save(dev, attrr)
**
strdevs = StorageService.list();
for(dev: strdevs) **
__attrr = dev.getAttrs();
**

более опытные индусы будут получать "сервисы" через IoC контейнер и накрутят интерфейсов
Гость
14 - 10.11.2014 - 00:20
да, это будет лучше чем один жЫрный метод, но все равно не идеал, просто потому что сервисы получающие список устройств в принципе можно объединить одним интерфейсом, и перечислять их в цикле, т.к. в некоторых случаях они могут быть не в виде линейного списка, а в виде дерева\иерархии (usb устройства, контроллер-диск-разделы, или контроллер-диски и контроллер-рейд-разделы) то перечислять их стоит в колбек (для примитивных языков программирования тут вылезает паттерн visitor) и куча других тонкостей, это все требует вдумчивого подхода к проектированию, анализа требований (в т.ч. к отображению результатов) и т.п.
Гость
15 - 10.11.2014 - 09:26
Даже не знаю.
Я попробую, сравню... в этом ведь суть обучения...
Дело в том, что я не считаю эти задачи такими уж разными. Это всего-лишь сбор данных. Мне кажется, если я буду отдельно реализовывать методы для каждой отдельной железки - будет намного больше дублированного кода.
Но я попробую.
Гость
16 - 10.11.2014 - 21:47
>методы для каждой отдельной железки

суть была не в этом
Гость
17 - 11.11.2014 - 13:38
15-Добрых дел мастер >Жирный метод желательно конечно разбить.

Цитата:
Мне кажется, если я буду отдельно реализовывать методы для каждой отдельной железки - будет намного больше дублированного кода.
Не плоди сущностей больше чем необходимо. А многократное дублирование кода - это еще большее зло, так как при изменениях обязательно где нибудь что нибудь забудешь обновить.
Но, если хочется можешь создать некий базовый класс и в нем реализовать нечто общее для всех, а далее создать наследников от него для каждой железяки с учетом ее особенностей. А можно объявить простой интерфейс для работы с железякой, а потом просто в классах для работы с конкретной железякой реализовывать поддержку этого интерфейса. А тот кто захочет получить инфу о железяке будет использовать этот интерфейс для работы. Только при объявлении интерфейса не переборщи, это должно быть нечто простое и понятное.
Гость
18 - 13.11.2014 - 13:01
0-Добрых дел мастер > "я прочитал, что каждый метод должен помещаться на одном экране. " - теория хорошая штука, но не стоит воспринимать ее буквально, как многие местные гуру. :)


К списку вопросов
Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск




Copyright ©, Все права защищены