Introduction
This week I was tasked to refactor the ReadmeGenie. If you just arrived here, ReadmeGenie is my open-source project that uses AI to generate readmes based on the files that the user inputs.
Initially, my thoughts were, "The program is working fine. I’ve been developing it in an organized way since day one... so why change it?"
Well, after taking a week-long break from the project, I opened it up again and immediately thought, "What is this?"
Why refactor?
To give you some context, here’s an example: One of my core functions, which I once thought was perfect, turned out to be much more complex than necessary. During the refactoring process, I broke it down into five separate functions—and guess what? The code is much cleaner and easier to manage now.
Take a look at the original version of this function:
def generate_readme(file_paths, api_key, base_url, output_filename, token_usage): try: load_dotenv() # Check if the api_key was provided either as an environment variable or as an argument if not api_key and not get_env(): logger.error(f"{Fore.RED}API key is required but not provided. Exiting.{Style.RESET_ALL}") sys.exit(1) # Concatenate content from multiple files file_content = "" try: for file_path in file_paths: with open(file_path, 'r') as file: file_content += file.read() + "\\n\\n" except FileNotFoundError as fnf_error: logger.error(f"{Fore.RED}File not found: {file_path}{Style.RESET_ALL}") sys.exit(1) # Get the base_url from arguments, environment, or use the default chosenModel = selectModel(base_url) try: if chosenModel == 'cohere': base_url = os.getenv("COHERE_BASE_URL", "https://api.cohere.ai/v1") response = cohereAPI(api_key, file_content) readme_content = response.generations[0].text.strip() + FOOTER_STRING else: base_url = os.getenv("GROQ_BASE_URL", "https://api.groq.com") response = groqAPI(api_key, base_url, file_content) readme_content = response.choices[0].message.content.strip() + FOOTER_STRING except AuthenticationError as auth_error: logger.error(f"{Fore.RED}Authentication failed: Invalid API key. Please check your API key and try again.{Style.RESET_ALL}") sys.exit(1) except Exception as api_error: logger.error(f"{Fore.RED}API request failed: {api_error}{Style.RESET_ALL}") sys.exit(1) # Process and save the generated README content if readme_content[0] != '*': readme_content = "\n".join(readme_content.split('\n')[1:]) try: with open(output_filename, 'w') as output_file: output_file.write(readme_content) logger.info(f"README.md file generated and saved as {output_filename}") logger.warning(f"This is your file's content:\n{readme_content}") except IOError as io_error: logger.error(f"{Fore.RED}Failed to write to output file: {output_filename}. Error: {io_error}{Style.RESET_ALL}") sys.exit(1) # Save API key if needed if not get_env() and api_key is not None: logger.warning("Would you like to save your API key and base URL in a .env file for future use? [y/n]") answer = input() if answer.lower() == 'y': create_env(api_key, base_url, chosenModel) elif get_env(): if chosenModel == 'cohere' and api_key != os.getenv("COHERE_API_KEY"): if api_key is not None: logger.warning("Would you like to save this API Key? [y/n]") answer = input() if answer.lower() == 'y': create_env(api_key, base_url, chosenModel) elif chosenModel == 'groq' and api_key != os.getenv("GROQ_API_KEY"): if api_key is not None: logger.warning("Would you like to save this API Key? [y/n]") answer = input() if answer.lower() == 'y': create_env(api_key, base_url, chosenModel) # Report token usage if the flag is set if token_usage: try: usage = response.usage logger.info(f"Token Usage Information: Prompt tokens: {usage.prompt_tokens}, Completion tokens: {usage.completion_tokens}, Total tokens: {usage.total_tokens}") except AttributeError: logger.warning(f"{Fore.YELLOW}Token usage information is not available for this response.{Style.RESET_ALL}") logger.info(f"{Fore.GREEN}File created successfully") sys.exit(0)
1. Eliminate Global Variables
Global variables can lead to unexpected side effects. Keep the state within the scope it belongs to, and pass values explicitly when necessary.
2. Use Functions for Calculations
Avoid storing intermediate values in variables where possible. Instead, use functions to perform calculations when needed—this keeps your code flexible and easier to debug.
3. Separate Responsibilities
A single function should do one thing, and do it well. Split tasks like command-line argument parsing, file reading, AI model management, and output generation into separate functions or classes. This separation allows for easier testing and modification in the future.
4. Improve Naming
Meaningful variable and function names are crucial. When revisiting your code after some time, clear names help you understand the flow without needing to re-learn everything.
5. Reduce Duplication
If you find yourself copying and pasting code, it’s a sign that you could benefit from shared functions or classes. Duplication makes maintenance harder, and small changes can easily result in bugs.
Commiting and pushing to GitHub
1. Create a branch
I started by creating a branch using:
git checkout -b <branch-name> </branch-name>
This command creates a new branch and switches to it.
2. Making a Series of Commits
Once on the new branch, I made incremental commits. Each commit represents a logical chunk of work, whether it was refactoring a function, fixing a bug, or adding a new feature. Making frequent, small commits helps track changes more effectively and makes it easier to review the history of the project.
git status git add <file_name> git commit -m "Refactored function" </file_name>
3. Rebasing to Keep a Clean History
After making several commits, I rebased my branch to keep the history clean and linear. Rebasing allows me to reorder, combine, or modify commits before they are pushed to GitHub. This is especially useful if some of the commits are very small or if I want to avoid cluttering the commit history with too many incremental changes.
git rebase -i main
In this step, I initiated an interactive rebase on top of the main branch. The -i flag allows me to modify the commit history interactively. I could squash some of my smaller commits into one larger, cohesive commit. For instance, if I had a series of commits like:
Refactor part 1
Refactor part 2
Fix bug in refactor
I could squash them into a single commit with a clearer message
4. Pushing Changes to GitHub
Once I was satisfied with the commit history after the rebase, I pushed the changes to GitHub. If you’ve just created a new branch, you’ll need to push it to the remote repository with the -u flag, which sets the upstream branch for future pushes.
git push -u origin <branch-name> </branch-name>
5. Merging
In the last step I did a fast-forward merge to the main branch and pushed again
git checkout main # change to the main branch git merge --ff-only <branch-name> # make a fast-forward merge git push origin main # push to the main </branch-name>
Takeaways
Everything has room to improve. Refactoring may seem like a hassle, but it often results in cleaner, more maintainable, and more efficient code. So, the next time you feel hesitant about refactoring, remember: there’s always a better way to do things.
Even though I think it's perfect now, I will definitely have something to improve on my next commit.
위 내용은 ReadmeGenie 리팩토링의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

2 시간 이내에 Python의 기본 프로그래밍 개념과 기술을 배울 수 있습니다. 1. 변수 및 데이터 유형을 배우기, 2. 마스터 제어 흐름 (조건부 명세서 및 루프), 3. 기능의 정의 및 사용을 이해하십시오. 4. 간단한 예제 및 코드 스 니펫을 통해 Python 프로그래밍을 신속하게 시작하십시오.

Python은 웹 개발, 데이터 과학, 기계 학습, 자동화 및 스크립팅 분야에서 널리 사용됩니다. 1) 웹 개발에서 Django 및 Flask 프레임 워크는 개발 프로세스를 단순화합니다. 2) 데이터 과학 및 기계 학습 분야에서 Numpy, Pandas, Scikit-Learn 및 Tensorflow 라이브러리는 강력한 지원을 제공합니다. 3) 자동화 및 스크립팅 측면에서 Python은 자동화 된 테스트 및 시스템 관리와 같은 작업에 적합합니다.

2 시간 이내에 파이썬의 기본 사항을 배울 수 있습니다. 1. 변수 및 데이터 유형을 배우십시오. 이를 통해 간단한 파이썬 프로그램 작성을 시작하는 데 도움이됩니다.

10 시간 이내에 컴퓨터 초보자 프로그래밍 기본 사항을 가르치는 방법은 무엇입니까? 컴퓨터 초보자에게 프로그래밍 지식을 가르치는 데 10 시간 밖에 걸리지 않는다면 무엇을 가르치기로 선택 하시겠습니까?

Fiddlerevery Where를 사용할 때 Man-in-the-Middle Reading에 Fiddlereverywhere를 사용할 때 감지되는 방법 ...

Python 3.6에 피클 파일로드 3.6 환경 보고서 오류 : modulenotfounderror : nomodulename ...

경치 좋은 스팟 댓글 분석에서 Jieba Word 세분화 문제를 해결하는 방법은 무엇입니까? 경치가 좋은 스팟 댓글 및 분석을 수행 할 때 종종 Jieba Word 세분화 도구를 사용하여 텍스트를 처리합니다 ...

정규 표현식을 사용하여 첫 번째 닫힌 태그와 정지와 일치하는 방법은 무엇입니까? HTML 또는 기타 마크 업 언어를 다룰 때는 정규 표현식이 종종 필요합니다.


핫 AI 도구

Undresser.AI Undress
사실적인 누드 사진을 만들기 위한 AI 기반 앱

AI Clothes Remover
사진에서 옷을 제거하는 온라인 AI 도구입니다.

Undress AI Tool
무료로 이미지를 벗다

Clothoff.io
AI 옷 제거제

AI Hentai Generator
AI Hentai를 무료로 생성하십시오.

인기 기사

뜨거운 도구

Atom Editor Mac 버전 다운로드
가장 인기 있는 오픈 소스 편집기

mPDF
mPDF는 UTF-8로 인코딩된 HTML에서 PDF 파일을 생성할 수 있는 PHP 라이브러리입니다. 원저자인 Ian Back은 자신의 웹 사이트에서 "즉시" PDF 파일을 출력하고 다양한 언어를 처리하기 위해 mPDF를 작성했습니다. HTML2FPDF와 같은 원본 스크립트보다 유니코드 글꼴을 사용할 때 속도가 느리고 더 큰 파일을 생성하지만 CSS 스타일 등을 지원하고 많은 개선 사항이 있습니다. RTL(아랍어, 히브리어), CJK(중국어, 일본어, 한국어)를 포함한 거의 모든 언어를 지원합니다. 중첩된 블록 수준 요소(예: P, DIV)를 지원합니다.

맨티스BT
Mantis는 제품 결함 추적을 돕기 위해 설계된 배포하기 쉬운 웹 기반 결함 추적 도구입니다. PHP, MySQL 및 웹 서버가 필요합니다. 데모 및 호스팅 서비스를 확인해 보세요.

Dreamweaver Mac版
시각적 웹 개발 도구

메모장++7.3.1
사용하기 쉬운 무료 코드 편집기
