TGViewer
Эргономичный код Эргономичный код @ergonomic_code · 837 subscribers
Post #677 742
Привет!

Знаете старую преподскую шутку - "Я им 5 раз объяснил, сам уже начал понимать, а они - не в какую!"?

Так вот я тут в попытках объяснить ИИ как писать хороший код, сам сделал хороший шаг в понимании этого:)

Жемчужину откопал там где не ждал - в "Чистом коде" анкл Боба в разделе про единственный уровень абстракции. Который, кстати, перечитывал недавно, но в тот раз пропустил.

Так вот жемчужина - техника объяснения кода в терминах "Чтобы ...".

To say this differently, we want to be able to read the program as though it were a set of TO paragraphs, each of which is describing the current level of abstraction and referencing subsequent TO paragraphs at the next level down.

To include the setups and teardowns, we include setups, then we include the test page content, and then we include the teardowns.
To include the setups, we include the suite setup if this is a suite, then we include the regular setup.
To include the suite setup, we search the parent hierarchy for the “SuiteSetUp” page and add an include statement with the path of that page.
To search the parent. . .


—

Иными словами, мы хотим иметь возможность читать программу так, как если бы она представляла собой набор абзацев "ЧТОБЫ...", каждый из которых описывает текущий уровень абстракции и ссылается на последующие абзацы "ЧТОБЫ" следующего, более низкого уровня.

Чтобы включить подготовительные и завершающие действия, мы сначала включаем setups, затем содержимое тестовой страницы, а затем teardowns.
Чтобы включить setups, мы включаем suite setup, если это набор тестов (suite), затем включаем обычный setup.
Чтобы включить suite setup, мы ищем в иерархии родительских страниц страницу “SuiteSetUp” и добавляем директиву include с путём к этой странице.
Чтобы выполнить поиск в родительской иерархии…


— Robert C. Martin, Clean Code, p. 37


Но это крутой инструмент не только для определения уровня абстракции функции, но и для определения её связности (cohesion).

Если функция имеет несколько несвязанных эффектов (коммуникационная и ниже связность), то её не получится описать в таком виде и без "и".

Например функция создания записей в дневнике в Проекте Э:

    override operator fun createEvents(
userId: Int,
eventsRqs: List<EditEventRq<out EventData>>,
): List<Event> {
val profileId = profilesRepo.lockOnProfile(userId)
val deduplicatedEvents = deduplicateEvents(eventsRequest, profileId)
when (deduplicatedEvents) {
is EventListWithInvalidDuplicates -> throw DifferentEventsWithSameId(userId, deduplicatedEvents.values)
is EventListWithFullDuplicates -> {
log.warn("...")
}

else -> {}
}

val existEventsIds = eventsRepo.findAllIdsByIdIn(deduplicatedEvents.values.map { it.id })
var actuallyNewEvents = deduplicatedEvents.values.filter { it.id !in existEventsIds }

eventsRepo.saveAll(actuallyNewEvents)

val lastUsedDeviceSerialNumber = eventsRepo.getLastUsedDeviceSerialNumberByProfile(profileId)
val domainEvents = actuallyNewEvents
.mapNotNull { DiaryEventCreated.fromDto(userId, it, lastUsedDeviceSerialNumber) }
eventsCreatedQueue.publishEvents(domainEvents)

return savedEvents
}


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

Но на самом деле - коммуникационная: Чтобы создать события мы блокируем профиль, дедуплицируем события, находим действительно новые события, сохраняем их в БД и публикуем сообщение об их создании. А публикуем мы сообщение - точно для того, "чтобы создать события"? Нет. Эта операция имеет две ответственности: создать события и оповестить об этом заинтересованные лица - "чтобы создать события и оповестить об этом мы...".
  • 👍 7
More from @ergonomic_code
  1. Sep 25, 2026photo post
  2. Sep 25, 2026Привет! Ну чтож. У меня наконец-то оглушительный успех с 100%-вайбкодингом. Знакомьтесь -…
  3. Sep 23, 2026Про творческий беспорядок в процессах Я куда ни приду лидом, меня первое время все ругают…
  4. Sep 23, 2026Саша пишет про процессы, как всегда очень круто, имхо
  5. Sep 4, 2026Post #717
  6. Aug 14, 2026Привет! Простые CRUD-приложения - это сложно Если помните, я уже писал, что с момента пере…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →