bespoyasov / refactor-like-a-superhero Goto Github PK
View Code? Open in Web Editor NEWHow to refactor code efficiently and without pain.
Home Page: https://refactoring-book.vercel.app/
License: Other
How to refactor code efficiently and without pain.
Home Page: https://refactoring-book.vercel.app/
License: Other
Опечатка в примере кода. Как я понимаю, должно быть auction.participants.filter(ownsLot)
// При выводе участников, которые победили по лотам:
function defineWinners(auction) {
return { ...auction, winners: participants.filter(ownsLot) };
}
Ниже, пропущен предлог в
Обычно его стоит добавлять места, где есть
Привет. Возможно ерунда и не стоит капать вглубь, поэтому смотри сам, стоит ли править, но просто опишу свои мысли.
Действия внутри функции меняют массив items
Вот тут смотря что имеется ввиду под "изменениями массива". Для меня это добавление, удаление или замена элемента. Тут же мы получили массив ссылок на объекты, и вернули этот же массив с этими же ссылками на объекты. Ничего по сути не изменилось. Замутировали как раз объекты. Поэтому фраза Действия внутри функции меняют массив items
читается как-то странно. Да, в целом, понятно из примера что имеется ввиду, но могут найтись люди, которым этот момент тоже может показаться странным. Да и то, что тут подымается тема мутации, работе по ссылке вроде как заставляет более аккуратно относиться к словам про изменения. Поэтому меня так зацепила эта фраза "меняют массив". Сам пример и цепочка рассуждений хорошая. Вот, думал, может чуть-чуть как-то слова про изменение массива вначале подобрать, чтобы было технически "правильнее" что ли, а не поверхностно-человечески, в духе "ну да, в целом обычный человек может сказать что массив поменялся, раз поменялось что-то в одном из контейнеров, что этот массив хранил":)
Просто мысли:) Возможно это всё и не нужно, поэтому через ишью, а не ПР:)
In README.md 'technics' should be 'techniques'.
Сигнатура функций не сообщает, что они могут выбросить ошибку — мы можем узнать об ошибках только из исходников.
Тут я сразу подумал о типе never
. Вроде мы можем этим намекнуть, что в коде может быть брошена ошибка. Да, мы не понимаем, что именно это за ошибка через типы как у тебя ниже, FetchUserError
или ParseUserError
. Но в контексте фразы, читается так, что never чисто технически, но грубо, может намекнуть на наличие выбрасывания через сигнатуру. Может быть это стоит упомянуть как-то.
Should be: ...Обычно достаточно воспринимать данные, как неизменяемые.
Говоря о зацеплении и интеграции модулей, стоит упомянуть управление зависимостями.
Под зависимостями для простоты будем иметь в виду любой код, который используется нашим
. Например, в функции randomInt кроме двух аргументов мы используем метод Math.random — это зависимость:
Предложение кажется не законченным, возможно стоит что-то добавить?
Когда пробую понять эти преобразования, возникает какое-то противоречие, как будто где-то ошибка.
// Вынесем 2-е вложенное условие в переменную:
const hasAdvantage = hasHeavyArmor || hasResistance;
// Заметим, что по первому закону де Моргана
// 1-е вложенное условие превратится в !hasAdvantage:
//
// !A || !B === !(A && B)
//
// A -> hasHeavyArmor
// B -> hasResistance
//
// !hasHeavyArmor || !hasResistance
// === !(hasHeavyArmor && hasResistance)
// === !hasAdvantage
// Тогда всё условие станет выглядеть так:
if (hasHighScore && !hasAdvantage) {
} else if (!hasHighScore && hasAdvantage) {
}
Либо я неправильно применяю, но у меня в голове так должно быть:
const hasAdvantage = hasHeavyArmor || hasResistance;
накидываем отрицание на две стороны
!hasAdvantage = !(hasHeavyArmor || hasResistance)
по закону это так
!(hasHeavyArmor || hasResistance) = !hasHeavyArmor && !hasResistance
И глядя на то, что у тебя написано !hasHeavyArmor || !hasResistance
, в
// !hasHeavyArmor || !hasResistance
// === !(hasHeavyArmor && hasResistance)
// === !hasAdvantage
вызывает вопросы:)
Но я даже пример собрал, и if (!hasAdvantage) {
и if (!hasHeavyArmor || !hasResistance) {
не взаимозаменяемыми выходят.
// readLogEntry.test.ts
describe("when given an ID", () => {
it("should call the logger service with that ID", () => {
const spy = jest.spyOn(logger, "getById");
readLogEntry("test-entry-id");
expect(spy).toHaveBeenCalledWith("test-entry-id");
});
});
// createLogEntry.test.ts
describe("when given an ID", () => {
it("should call the logger service create with that ID and default entry data", () => {
const spy = jest.spyOn(logger, "createEntry");
createLogEntry("test-entry-id");
expect(spy).toHaveBeenCalledWith("test-entry-id", timeStub, "Access");
});
});
С тестом createLogEntry
ок, тестируем видимое поведение - вызов (эффект). Со сценарием вызова лога в readLogEntry
тоже ок. Но что с другими сценариями? Да, чтобы не раздувать всеми тестами текст, вроде можно опустить. Но выше мы вводили читателя в тестирование возвращаемого результата. А сейчас как будто лишили его этих проверок, показав важность лишь проверки вызова. Но тут такие моменты. Если мы из readLogEntry
уберем return
, то тест пройдет. Мы можем написать тест на сценарий возврата null
без мока логгера. Но сценарий ветки, где возврат значения после отработки логгера ведь тоже важен? Вдруг код изменят так, что вызов лога останется, но возврат потеряется. И такое без мока logger.getById
не сделать? То есть, от моков мы в этом сценарии не уйдем? Или я чего-то не понял:)
First of all, thanks a lot for your book :) I was wondering if it is possible to share the website source: https://refactoring-book.vercel.app/en.
I read that it was developed with Svelte, but I need help finding the source—many thanks for considering my request.
David
In our project we have global error handler for all errors. It's pretty easy to handle because we have one entity for Error handling. If something goes wrong in Error handling we going to ErrorService and work only with this entity.
We throw all errors (panic errors) and they catched by listeners.
`class ErrorService {
errors: ProjectError[] = [];
constructor (window) {
this.global = window;
}
listen() {
global.addEventListener('error', (e) => {
// error object creation and pushing error to errors array. We can add additional logic (e.g. counter of errors if there is multiple same errors on page, sending data to Sentry and etc.)
})
global.addEventListener('unhandledRejection', (e) => {
//same here
})
}
}
//at root level of app
const errorService = new ErrorService(window);
errorService.listen();
`
Может быть стоит добавить в дополнение к “Refactoring” by Martin Fowler, Kent Beck, https://www.goodreads.com/book/show/44936.Refactoring ту же книгу на русском языке? https://www.ozon.ru/product/refaktoring-koda-na-javascript-uluchshenie-proekta-sushchestvuyushchego-koda-156082567/?sh=tx6m_osG8g
Когда читал Типы для описания домена возникли мысли о структурной типизации, потому что обычно читая примеры кода, где статическая типизация во фронте, думаешь сразу о Typescript. Из-за этого перед врезкой "Подробнее", напрашивается еще одна врезка, например, "К слову", где можно упомянуть о структурной типизации, и что из-за неё у нас не будет 100% защиты от использования "неправильного" типа по смысловому неймингу домена, как в случае с номинативной.
Были ли такие мысли и опустил это намеренно, чтобы не перегружать текст? Что думаешь?
В целом, по тексту всей книги не нашел упоминания структурной типизации. Может быть стоит где-то сделать про это вброс в контексте рефакторинга или чего-то ещё, только пока не знаю, что предложить, так как дальше книгу не читал ещё.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.