pan7ae / professional_task Goto Github PK
View Code? Open in Web Editor NEWЛабораторная работа по рефакторингу кода и обратному проектированию
Лабораторная работа по рефакторингу кода и обратному проектированию
Неправильные отступы могут привести к ошибкам компиляции или неправильной интерпретации кода.
Проблема может быть связана с неправильным форматированием кода, несоблюдением правил оформления отступов в соответствии со стандартом PEP 8, использованием табуляции вместо пробелов и т.д. Отсутствие правильных отступов может привести к трудностям в чтении и понимании кода другими программистами
async def create_promotion(
promo_data: PromoCreate = Depends(PromoCreate.as_form),
service: PromoService = Depends(get_promo_service)
):
return await service.create(promo_data)
В данном случае, отступы перед строками promo_data: PromoCreate = Depends(PromoCreate.as_form)
, и service: PromoService = Depends(get_promo_service)
должны состоять из 4 пробелов в соответствии со стандартом PEP 8, но здесь используется неправильное количество пробелов и табуляция.
async def get_promotion(
promo_id: int,
service: PromoService = Depends(get_promo_service)):
return await service.get(promo_id)
В данном случае, отступы перед строками promo_id: int
, и service: PromoService = Depends(get_promo_service)):
должны состоять из 4 пробелов в соответствии со стандартом PEP 8, но здесь используется неправильное количество пробелов и табуляция.
async def update_promotion(
promo_id: int,
promo_data: PromoUpdate = Depends(PromoUpdate.as_form),
service: PromoService = Depends(get_promo_service)):
return await service.update(promo_id, promo_data)
В данном случае, отступы перед строками promo_id: int
, promo_data: PromoUpdate = Depends(PromoUpdate.as_form)
и service: PromoService = Depends(get_promo_service)):
должны состоять из 4 пробелов в соответствии со стандартом PEP 8, но здесь используется неправильное количество пробелов и табуляция.
async def delete_promotion(
promo_id: int,
service: PromoService = Depends(get_promo_service)):
return await service.delete(promo_id)
В данном случае, отступы перед строками promo_id: int
, и service: PromoService = Depends(get_promo_service)):
должны состоять из 4 пробелов в соответствии со стандартом PEP 8, но здесь используется неправильное количество пробелов и табуляция.
async def create_participant(
promo_id: int,
user_data: UserCreate = Depends(UserCreate.as_form),
service: PromoService = Depends(get_promo_service)
):
pass
В данном случае, отступы перед строками promo_id: int
, user_data: UserCreate = Depends(UserCreate.as_form)
и service: PromoService = Depends(get_promo_service)
должны состоять из 4 пробелов в соответствии со стандартом PEP 8, но здесь используется неправильное количество пробелов и табуляция.
async def delete_participant(
promo_id: int,
participant_id: int,
service: PromoService = Depends(get_promo_service)):
pass
В данном случае, отступы перед строками promo_id: int
, uparticipant_id: int,
и service: PromoService = Depends(get_promo_service)):
должны состоять из 4 пробелов в соответствии со стандартом PEP 8, но здесь используется неправильное количество пробелов и табуляция.
async def create_prize(
prize_data: PrizeCreate = Depends(PrizeCreate.as_form),
service: PromoService = Depends(get_promo_service)
):
pass
В данном случае, отступы перед строками prize_data: PrizeCreate = Depends(PrizeCreate.as_form),
и service: PromoService = Depends(get_promo_service)
должны состоять из 4 пробелов в соответствии со стандартом PEP 8, но здесь используется неправильное количество пробелов и табуляция.
async def delete_prize(
promo_id: int,
prize_id: int,
service: PromoService = Depends(get_promo_service)):
pass
В данном случае, отступы перед строками promo_id: int,
, prize_id: int,
и service: PromoService = Depends(get_promo_service)):
должны состоять из 4 пробелов в соответствии со стандартом PEP 8, но здесь используется неправильное количество пробелов и табуляция.
async def promotion_result(
promo_id: int,
service: PromoService = Depends(get_promo_service)
):
pass
В данном случае, отступы перед строками promo_id: int,
, и service: PromoService = Depends(get_promo_service)):
должны состоять из 4 пробелов в соответствии со стандартом PEP 8, но здесь используется неправильное количество пробелов и табуляция.
def as_form(
cls,
description: str = Form(None)):
return cls(name=description)
В данном случае, отступы перед строками cls,
, и description: str = Form(None)):
должны состоять из 4 пробелов в соответствии со стандартом PEP 8, но здесь используется неправильное количество пробелов и табуляция.
def as_form(
cls,
name: str = Form(...),
description: Optional[str] = Form(None)):
return cls(name=name, description=description)
В данном случае, отступы перед строками cls,
, name: str = Form(...),
и description: Optional[str] = Form(None)):
должны состоять из 4 пробелов в соответствии со стандартом PEP 8, но здесь используется неправильное количество пробелов и табуляция.
def as_form(
cls,
name: str = Form(...)):
return cls(name=name)
В данном случае, отступы перед строками cls,
и name: str = Form(...),
должны состоять из 4 пробелов в соответствии со стандартом PEP 8, но здесь используется неправильное количество пробелов и табуляция.
Висящая закрывающая скобка в блоке параметров функции может вызвать путаницу и затруднить чтение кода другим программистам. Это может привести к ошибкам при попытке понять и использовать функцию. (Не считаю это большой ошибкой форматирования кода, но нужно оформлять все в едином стиле)
Вероятно, это связано с неправильным форматированием кода при написании функции.
async def create_promotion(
promo_data: PromoCreate = Depends(PromoCreate.as_form),
service: PromoService = Depends(get_promo_service)
):
return await service.create(promo_data)
Необходимо обратить внимание на строку 26. Закрывающая скобка должна быть на той же строке, что и параметры функции.
async def create_participant(
promo_id: int,
user_data: UserCreate = Depends(UserCreate.as_form),
service: PromoService = Depends(get_promo_service)
):
pass
Необходимо обратить внимание на строку 57. Закрывающая скобка должна быть на той же строке, что и параметры функции.
async def create_prize(
prize_data: PrizeCreate = Depends(PrizeCreate.as_form),
service: PromoService = Depends(get_promo_service)
):
pass
Необходимо обратить внимание на строку 73. Закрывающая скобка должна быть на той же строке, что и параметры функции.
async def promotion_result(
promo_id: int,
service: PromoService = Depends(get_promo_service)
):
pass
Необходимо обратить внимание на строку 89. Закрывающая скобка должна быть на той же строке, что и параметры функции.
Затруднение чтения и понимания кода, а также возможность создания конфликтов имен переменных в случае использования алиасов. Это может привести к ошибкам и багам.
Алиасы могут быть использованы для сокращения длинных имен модулей или для предотвращения конфликтов имен переменных при импорте нескольких модулей, но их неправильное использование может привести к проблемам.
import sqlalchemy as sa
В данном участке кода проблема состоит в том, что имя библиотеки импортируется как "sa
", что может быть не понятным для других программистов, которые будут читать этот код. Хорошей практикой является использование полных имен библиотек или стандартных сокращений, таких как "sqlalchemy
".
Затруднения в поиске и идентификации файлов, путаница при работе с проектом. Это может привести к ошибкам при импортировании модулей и усложнить понимание структуры проекта.
Проблема дублирования названий файлов могла возникнуть из-за неправильного планирования и организации структуры проекта. Возможно, разработчик не обратил внимания на существующие файлы с таким же названием или не следовал правилам именования файлов.
professional_task/
├── src/
└──promotions/
├── api
├── __init__.py
├── depends.py
└── promo.py
├── db/
├── __init__.py
├── database.py
├── prize.py
├── promotion.py
└── user.py
├── models/
├── __init__.py
├── prize.py
├── promotion.py
├── result.py
└── user.py
├── services/
├── __init__.py
└── promo.py
├── __init__.py
├── config.py
└── main.py
├── venv/
├── .env
├── .gitignore
├── docker-compose.yml
├── Dockerfile
├── README.md
└── requirements.txt
Для исправления проблемы рекомендуется переименовать дублирующиеся файлы или переорганизовать структуру проекта, чтобы избежать конфликта имен файлов.
Непонятные названия методов могут затруднить понимание функциональности и назначения этих методов. Это может привести к ошибкам при использовании или поддержке кода и усложнить его чтение и понимание для других разработчиков.
Проблема непонятных названий методов могла возникнуть из-за недостаточного внимания к неймингу или отсутствия ясной конвенции именования методов. Возможно, разработчик не уделил достаточного внимания важности понятных и информативных названий методов.
async def _get(self, promo_id: int) -> PromoWithDetails:
query = promotions.select().where(promotions.c.id == promo_id)
promo = await self.database.fetch_one(query=query)
if not promo:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return PromoWithDetails.parse_obj(promo)
async def get_list(self) -> List[Promo]:
query = promotions.select()
return await self.database.fetch_all(query=query)
async def get(self, promo_id: int) -> PromoWithDetails:
return await self._get(promo_id)
Для исправления проблемы рекомендуется переименовать методы с более информативными и понятными названиями, отражающими их функциональность и назначение. Это поможет сделать код более читаемым и понятным для других разработчиков.
Непонятные названия методов (create, update, delete) могут затруднить понимание того, что конкретно выполняют эти методы. Это может привести к путанице и ошибкам при использовании методов, особенно для других разработчиков, которые могут работать с этим кодом. Также это может привести к ошибкам и непредсказуемому поведению, особенно при использовании этих методов в других частях кода или при работе с API.
Проблема непонятных названий методов (create, update, delete) может возникнуть из-за отсутствия ясности и информативности в выборе имен методов. Разработчик, создавший эти методы, мог не уделить достаточного внимания понятности и информативности их названий, что привело к затруднениям в их использовании и понимании.
async def create(self, promo_data: PromoCreate):
promo = PromoCreate(**promo_data.dict())
values = {**promo.dict()}
query = promotions.insert().values(**values)
promo_res = await self.database.execute(query=query)
return promo_res
async def update(self, promo_id: int, promo_data: PromoUpdate) -> Promo:
promo = await self._get(promo_id)
for field, value in promo_data:
if value:
setattr(promo, field, value)
values = {**promo.dict()}
query = promotions.update().where(promotions.c.id == promo_id).values(**values)
await self.database.execute(query=query)
return promo
async def delete(self, promo_id: int):
await self._get(promo_id)
query = promotions.delete().where(promotions.c.id == promo_id)
return await self.database.execute(query=query)
Для исправления проблемы рекомендуется переименовать методы таким образом, чтобы они точно отражали свою функциональность. Например, можно использовать более информативные и понятные названия, указывающие на конкретные действия, которые выполняются. Например, вместо "create" можно использовать "create_promotion", вместо "update" – "update_promotion", а вместо "delete" – "delete_promotion". Это поможет улучшить читаемость и понимание кода другими разработчиками.
Проблема относится к файлам prize.py
, promotion.py
и user.py
в директории src/promotion/db/
, где определения таблиц повторяются:
prizes = sa.Table(
"prizes",
metadata,
sa.Column("id", sa.Integer, primary_key=True, autoincrement=True, unique=True),
sa.Column("description", sa.String, nullable=True)
)
promotions = sa.Table(
"promotions",
metadata,
sa.Column("id", sa.Integer, primary_key=True, autoincrement=True, unique=True),
sa.Column("name", sa.String, nullable=False),
sa.Column("description", sa.String, nullable=True),
sa.Column("prizes", sa.ARRAY(sa.Integer), nullable=True),
sa.Column("participants", sa.ARRAY(sa.Integer), nullable=True)
)
users = sa.Table(
"users",
metadata,
sa.Column("id", sa.Integer, primary_key=True, autoincrement=True, unique=True),
sa.Column("name", sa.String, unique=True),
)
Рекомендуется вынести определения таблиц в отдельный модуль или класс, который будет общим для всех модулей и предоставлять определения таблиц для использования. Это позволит избежать дублирования кода, сделает код более согласованным и улучшит его поддержку и изменение.
Неиспользуемый код не выполняет никаких полезных действий и может привести к лишней сложности в понимании кода. Это может затруднить поддержку и обновление кода в будущем. Функция не будет использоваться в коде, что может привести к ненужному расходованию ресурсов.
Функция была определена, но не была вызвана в коде. Также неиспользуемый код может возникнуть, если в процессе разработки были внесены изменения в функцию, и определенные части кода стали ненужными.
async def create_participant(
promo_id: int,
user_data: UserCreate = Depends(UserCreate.as_form),
service: PromoService = Depends(get_promo_service)
):
pass
async def delete_participant(
promo_id: int,
participant_id: int,
service: PromoService = Depends(get_promo_service)):
pass
async def create_prize(
prize_data: PrizeCreate = Depends(PrizeCreate.as_form),
service: PromoService = Depends(get_promo_service)
):
pass
async def delete_prize(
promo_id: int,
prize_id: int,
service: PromoService = Depends(get_promo_service)):
pass
async def promotion_result(
promo_id: int,
service: PromoService = Depends(get_promo_service)
):
pass
Удалить функцию, если она не нужна в программе, или добавить вызов этой функции в нужном месте кода. Если функция была намеренно оставлена без использования для будущего использования, то необходимо добавить комментарий с указанием этой цели.
Отсутствие модульных тестов может привести к следующим проблемам:
Отсутствие модульных тестов может возникнуть по следующим причинам:
Для исправления данной проблемы рекомендуется добавить модульные тесты для каждого эндпоинта. Модульные тесты позволят проверить корректность работы каждого эндпоинта в изоляции, обнаружить ошибки и дефекты, а также обеспечить надежность и уверенность в работе кода.
Отсутствие аннотации типов может затруднить чтение и понимание кода другими разработчиками, а также привести к ошибкам типизации и неожиданным поведениям в случае передачи неправильных аргументов.
Отсутствие аннотаций типов усложняет понимание типов данных, которые принимаются и возвращаются функцией. Это может привести к ошибкам при вызове функции с аргументами неправильного типа, а также усложнить работу с кодом в будущем.
Возможно, разработчик не был достаточно внимателен при написании кода или не имел достаточного опыта работы с аннотациями типов в Python – это маловероятно, т.к. в большинстве случаев она все-таки есть. Либо это старый код, написанный до введения поддержки аннотаций типов в Python, что также маловероятно.
async def get_promotions(service: PromoService = Depends(get_promo_service)):
return await service.get_list()
async def create_promotion(
promo_data: PromoCreate = Depends(PromoCreate.as_form),
service: PromoService = Depends(get_promo_service)
):
return await service.create(promo_data)
async def get_promotion(
promo_id: int,
service: PromoService = Depends(get_promo_service)):
return await service.get(promo_id)
async def update_promotion(
promo_id: int,
promo_data: PromoUpdate = Depends(PromoUpdate.as_form),
service: PromoService = Depends(get_promo_service)):
return await service.update(promo_id, promo_data)
async def delete_promotion(
promo_id: int,
service: PromoService = Depends(get_promo_service)):
return await service.delete(promo_id)
@classmethod
def as_form(
cls,
description: str = Form(None)):
return cls(name=description)
@classmethod
def as_form(
cls,
name: str = Form(...),
description: Optional[str] = Form(None)):
return cls(name=name, description=description)
@classmethod
def as_form(
cls,
name: str = Form(...)):
return cls(name=name)
async def create(self, promo_data: PromoCreate):
promo = PromoCreate(**promo_data.dict())
values = {**promo.dict()}
query = promotions.insert().values(**values)
promo_res = await self.database.execute(query=query)
return promo_res
async def delete(self, promo_id: int):
await self._get(promo_id)
query = promotions.delete().where(promotions.c.id == promo_id)
return await self.database.execute(query=query)
Для устранения данной проблемы следует добавить аннотации типов для параметров функции и/или возвращаемого значения.
Хранение захардкоженных паролей в docker-compose.yml может привести к следующим проблемам:
Хранение захардкоженных паролей в docker-compose.yml может возникнуть по следующим причинам:
services:
db_promotion:
image: postgres:13-alpine
# ...
environment:
- POSTGRES_USER=fastapi_promotion
- POSTGRES_PASSWORD=fastapi_promotion
- POSTGRES_DB=fastapi_promotion
Для исправления данной проблемы рекомендуется использовать механизмы управления секретами, предоставляемые Docker или другими инструментами, например, Docker Secrets или переменные окружения. Это позволит изолировать конфиденциальные данные, такие как пароли, от кода и конфигурации, обеспечивая безопасность и гибкость в управлении секретами.
Также создание файла docker-compose.override.yml
может помочь в решении данной проблемы. Файл docker-compose.override.yml
предназначен для переопределения или расширения настроек, определенных в основном файле docker-compose.yml
.
Вы можете создать файл docker-compose.override.yml
и использовать его для определения конфигурации, включая конфиденциальные данные, такие как пароли. Ваш основной файл docker-compose.yml
будет ссылаться на этот файл, и настройки из docker-compose.override.yml
будут применяться при запуске контейнеров.
В коде отсутствует обработка исключений и установка общего таймаута для запросов к базе данных. Это может привести к блокировке приложения, если запрос к базе данных занимает слишком много времени, и нет механизма для прерывания этого запроса
Отсутствие обработки исключений при выполнении запросов к базе данных может привести к следующим проблемам:
Отсутствие обработки таймаута может быть вызвано незнанием или непредусмотрительностью разработчика при написании кода для выполнения запросов к базе данных. Возможно, разработчик не предусмотрел случаев, когда запрос может занимать слишком много времени из-за проблем с сетью, нагрузкой на БД или других факторов.
@app.on_event("startup")
async def startup():
await database.connect()
@app.on_event("shutdown")
async def shutdown():
await database.disconnect()
Для решения данной проблемы необходимо добавить обработку исключений и установить общий таймаут для запросов к базе данных. Это позволит предотвратить блокировку приложения и обеспечить его отзывчивость.
Т.е. можно добавить обработку исключений и установить общий таймаут, например, в 60 секунд для запросов к базе данных при запуске и остановке приложения.
src/promotion/services/promo.py Строки 10 – 53
class PromoService:
def __init__(self, database: Database):
self.database = database
async def _get(self, promo_id: int) -> PromoWithDetails:
query = promotions.select().where(promotions.c.id == promo_id)
promo = await self.database.fetch_one(query=query)
if not promo:
raise HTTPException(status_code=status.HTTP_404_NOT_FOUND)
return PromoWithDetails.parse_obj(promo)
async def get_list(self) -> List[Promo]:
query = promotions.select()
return await self.database.fetch_all(query=query)
async def get(self, promo_id: int) -> PromoWithDetails:
return await self._get(promo_id)
async def create(self, promo_data: PromoCreate):
promo = PromoCreate(**promo_data.dict())
values = {**promo.dict()}
query = promotions.insert().values(**values)
promo_res = await self.database.execute(query=query)
return promo_res
async def update(self, promo_id: int, promo_data: PromoUpdate) -> Promo:
promo = await self._get(promo_id)
for field, value in promo_data:
if value:
setattr(promo, field, value)
values = {**promo.dict()}
query = promotions.update().where(promotions.c.id == promo_id).values(**values)
await self.database.execute(query=query)
return promo
async def delete(self, promo_id: int):
await self._get(promo_id)
query = promotions.delete().where(promotions.c.id == promo_id)
return await self.database.execute(query=query)
Рекомендуется разделить класс PromoService
на отдельные классы, каждый из которых будет выполнять только одну конкретную задачу, соответствуя принципу SRP. Это улучшит понимание и поддержку кода, сделает его более гибким и легко расширяемым.
Разделение моделей по разным файлам может затруднить их обнаружение и понимание структуры проекта. Это усложняет поддержку и разработку кода, особенно при работе с большими проектами. Кроме того, разбросанные модели могут привести к дублированию кода и несогласованности между моделями, что может привести к ошибкам и неоднозначности.
Разделение моделей по разным файлам могло возникнуть из-за неоптимальной организации кода или отсутствия ясных принципов и стандартов для структурирования моделей.
professional_task/ ├── src/ └──promotions/ ├── api/ ├── db/ ├── models/ ├── __init__.py ├── prize.py ├── promotion.py ├── result.py └── user.py ├── services/ ├── __init__.py ├── config.py └── main.py ├── venv/ ├── .env ├── .gitignore ├── docker-compose.yml ├── Dockerfile ├── README.md └── requirements.txt
Для исправления проблемы рекомендуется объединить модели, которые имеют связь или взаимосвязь, в один файл. Например, можно создать файл models.py
и поместить в него все модели. Это упростит понимание структуры данных и улучшит обслуживание кода.
В коде отсутствует использование механизма логирования, что затрудняет отслеживание и анализ происходящих событий и ошибок в приложении. Отсутствие логов может усложнить процесс отладки, мониторинга и выявления проблемных мест.
Проблема относится ко всему коду приложения, где отсутствует использование механизма логирования.
Для решения данной проблемы необходимо добавить механизм логирования в приложение. Рекомендуется использовать специализированные библиотеки или инструменты для логирования, такие как logging
в Python, которые предоставляют гибкость в настройке и уровнях логирования.
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.