All streams
Search
Write a publication
Pull to refresh
10
0
Сергей Клевакин @Justerest

User

Send message
Привет! Спасибо за статью. Очень смело.

Вы доказываете, что механическое перетаскивание кода из класса А в класс Б не приносит пользы. И Вы правы!

Потому что в Вашем коде нет никакого BL. И все слои вместе взятые — это одно сплошное императивное редактирование ячеек БД через HTTP запросы. (Как и в большинстве проектов, которые я видел).

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

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

// я про эти строчки
fromUser.Balance -= amount;
toUser.Balance += amount;


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

У меня по поводу красивости кода есть немного другая теория.
С помощью языка мы излагаем свои мысли. ЯП — это формализованный язык, он достаточно отличается от разговорного, на котором мы думаем. Из-за отличий, нам постоянно приходится переводить (компилировать) ЯП на русский, это напрягает мозг. Поэтому, чем код ближе к разговорному аналогу, тем он нам кажется красивее. Причем, так как мы говорим одни и те же вещи разными словами, поэтому мы и код воспринимаем субъективно. Вывод, код — вещь динамическая, как и любой другой язык общения. Нет смысла стремится делать его идеальным, поэтому что это равносильно написанию идеального четверостишия. (Решил написать комментарий после 4 часов миграции лодаш на рамда)
А я давно перешёл на json-material тему


Я не хочу разводить холивары, посыл статьи отличный — ограждаться от стороннего АПИ. В прокидывании Observable через InjectionToken тоже ничего плохого. Но если бы я захотел пользоваться такой утилиткой, то я бы ожидал примерно следующий GeolocationService.

@Injectable({ providedIn: 'root' })
export class GeolocationService {
	private geolocation?: Geolocation = this.document.defaultView?.navigator?.geolocation;

	constructor(@Inject(DOCUMENT) private document: Document) {}

	isSupported(): boolean {
		return !!this.geolocation;
	}

	getCurrentPosition(options?: PositionOptions): Observable<Position> {
		const geolocation = this.getGeolocationOrThrowError();
		return new Observable<Position>((subscriber) =>
			geolocation.getCurrentPosition(
				(position) => {
					subscriber.next(position);
					subscriber.complete();
				},
				(positionError) => subscriber.error(positionError),
				options,
			),
		);
	}

	private getGeolocationOrThrowError(): Geolocation {
		assert(this.geolocation, 'Geolocation is not supported in your browser');
		return this.geolocation;
	}

	watchPosition(options?: PositionOptions): Observable<Position> {
		const geolocation = this.getGeolocationOrThrowError();
		return new Observable<Position>((subscriber) => {
			const watchPositionId = geolocation.watchPosition(
				(position) => subscriber.next(position),
				(positionError) => subscriber.error(positionError),
				options,
			);
			return () => geolocation.clearWatch(watchPositionId);
		});
	}
}


На его основе я бы смог расшарить observable дальше как мне нужно (да, может быть сделать один глобальный position$).

Но через применение наследования вы смешали абстракции. Первая абстракция — адаптер над АПИ. Вторая абстаракция — расшаренный observable. (Я так считаю)
Пробовали заменять наследование композицией? Меньше токенов придётся плодить. И вообще, я не суеверный, но есть такой антипаттерн — Базовый класс-утилита (BaseBean): Наследование функциональности из класса-утилиты вместо делегирования к нему.
Пример того, когда автор может честно говорить, что думает. Да, грубовато. Но большинство статей про js намного токсичнее, хотя автор будет обращаться на «вы».
То что вы называете «алгоритмический код», я бы назвал «манкикодинг на время») Все приведённые примеры могут выглядеть и в 10 раз хуже, но где тесты? Или сроки не позволяют их использовать?)
По-моему, на Рефакторинг Гуру объясняется намного лучше. Если хочется ещё подробней, то обращайтесь к Банде Четырех.

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

А научиться hello electron можно по ходу дела. Страничка get started будет полезней вашей курсовой (можете преподу скинуть).

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

Но я понимаю, что с electron интересней, и преподам закатит…

По сути, вам просто было не чем заняться, потому что реализация «поиска в файле» — слабая тема для курсовой. Можно было бы проанализировать разные алгоритмы, дать пользователю возможность выбора алгоритма, производительность померить… Тогда ещё норм.

Это реальная проблема образования. Преподаватель не задал нужное направление, а вы просто прикрутили за уши к задаче стек, который вам интересен. У меня вся учёба в универе похожа на эту статью. Куда мир катится?)
Классно, что людям есть о чём написать, о чём поспорить… Для меня статья прозвучала так — у нас было медленно, а потом мы «прочитали книжки», и всё стало быстро!) Осталось с комментаторами разобраться, и объяснить, что мы делали!)
Эта статья давно меня заинтересовала… Изначально, я бесился из-за того, что в моей команде принято было писать статические методы вместо простых функций. Я понимаю, что в основном автор против маскирования функций за оболочкой класса (правило 2-х методов). Но позвольте:
Мы задаём эту задачу на собеседовании (игру Жизнь), потому что если вы не умеете такого — нам не о чем разговаривать.

Ребята, а сколько из вас реально понимают эти 10 строчек кода с полной реализацией игры Жизнь? Честно говоря, я не понимаю. Я читал это 2 года назад — не понимал. И сейчас не понимаю. Это реализация рисования пикселей на экране, а не игры! Что уж говорить про собеседование — я бы сразу ушёл((

Задача об игре Жизнь не укладывалась в моей голове, а самооценка сильно болела, пока я не убил денёк на свою реализацию — Жизнь/Core. И вот какой парадокс… Мой вариант не доработанный, с безумными абстракциями, на тучу строчек кода для меня выглядит намного естественней! Я знаю, как поменять правила, как замкнуть поле, как играть в трехмерном пространстве… Как запустить по этому полю Динозавра, откладывающего яйца!

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

И вот у меня вопрос, а не делятся ли разработчики на два типа:
1) Математики — жонглируют в голове 10 мячами, долго переключаются между абстракциями, пишут про «хватит классы».
2) Философы — быстро переключаются между абстракциями, не могут жонглировать более чем 3-мя мячами, пишут про ООП.

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


В декораторах из TypeScript/JavaScript нет ничего динамического. Они вешаются на конкретные классы (методы). Мне кажется, что стоит разделять паттерн Декоратор и декораторы в языке. Или я не прав?
Короче, Посетитель нужен там, где instance of не справляется. Если по-простому
Эх… Без примера не разобраться. Мы немного о разном.

Вот скажите, как ваша итоговая реализация будет ввести себя для класса, который одновременно расширяет и Cat и Human?

Как будет работать эта реализация для класса SuperHuman: Human? Который днём ведёт себя как обычный человек, а ночью летает?
Вы сводите паттерн Посетитель к элементарному вызову функции f(o). Зачем вообще какой-то паттерн, чтобы передать объект в функцию? Не надо приводить типы, это необязательно (в супер классе обычно есть общие методы).

Я каюсь, что не штудировал перед ответом GoF, да и Котлин не особо знаю. Но использую этот паттерн в одном проекте. И Посетитель как раз позволяет избавиться от конструкций switch (и их аналогов) в клиентском коде, предоставляя возможность объекту самостоятельно выбрать нужный метод посетителя.

Получается: ответственность за функциональность на посетителе, а ответственность за выбор нужного метода — внутри объекта.
По-моему, если бы вы сделали класс
interface Visitor {
    fun visitHuman(creature: LivingCreature)
    fun visitAnimal(creature: LivingCreature)
}

то стало бы понятно, что преимущество шаблона посетитель в том, что вы не зависите от конкретных классов. И экземпляр Human, если ему вдруг захочется, может сам решить — мяукать ему или разговаривать))
По-моему, все действия после первого примера с кодом являются нарушением KISS и YAGNI. Особенно handleChange со строкой в параметрах :)
А DRY больше про «не дублируйте логику», а не про экономию места.
Мне библиотека понравилась. Я воспользуюсь, если будет нужно. Это не критика. Это уточнения, мысли вслух. Воспоминания про свои такие библиотеки.

Information

Rating
Does not participate
Location
Екатеринбург, Свердловская обл., Россия
Date of birth
Registered
Activity