„Wenn ein Arbeiter seine Arbeit gut machen will, muss er zuerst seine Werkzeuge schärfen.“ – Konfuzius, „Die Gespräche des Konfuzius. Lu Linggong“
Titelseite > Programmierung > Refactoring von ReadmeGenie

Refactoring von ReadmeGenie

Veröffentlicht am 23.12.2024
Durchsuche:290

Refactoring ReadmeGenie

Einführung

Diese Woche wurde ich beauftragt, das ReadmeGenie zu überarbeiten. Wenn Sie gerade erst hier angekommen sind: ReadmeGenie ist mein Open-Source-Projekt, das mithilfe von KI Readme-Dateien basierend auf den vom Benutzer eingegebenen Dateien generiert.

Zuerst dachte ich: „Das Programm funktioniert gut. Ich habe es seit dem ersten Tag organisiert entwickelt … warum sollte ich es also ändern?“

Nun, nachdem ich eine Woche Pause vom Projekt gemacht hatte, öffnete ich es wieder und dachte sofort: „Was ist das?“

Warum umgestalten?

Um Ihnen etwas Kontext zu geben, hier ein Beispiel: Eine meiner Kernfunktionen, die ich einst für perfekt hielt, erwies sich als viel komplexer als nötig. Während des Refactoring-Prozesses habe ich es in fünf separate Funktionen zerlegt – und wissen Sie was? Der Code ist jetzt viel sauberer und einfacher zu verwalten.

Sehen Sie sich die Originalversion dieser Funktion an:

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. Globale Variablen eliminieren
Globale Variablen können zu unerwarteten Nebenwirkungen führen. Behalten Sie den Status innerhalb des Bereichs bei, zu dem er gehört, und übergeben Sie Werte bei Bedarf explizit.

2. Funktionen für Berechnungen verwenden
Vermeiden Sie nach Möglichkeit die Speicherung von Zwischenwerten in Variablen. Verwenden Sie stattdessen Funktionen, um bei Bedarf Berechnungen durchzuführen – so bleibt Ihr Code flexibel und einfacher zu debuggen.

3. Getrennte Verantwortlichkeiten
Eine einzelne Funktion sollte eine Sache tun, und zwar gut. Teilen Sie Aufgaben wie das Parsen von Befehlszeilenargumenten, das Lesen von Dateien, die KI-Modellverwaltung und die Ausgabegenerierung in separate Funktionen oder Klassen auf. Diese Trennung ermöglicht ein einfacheres Testen und Ändern in der Zukunft.

4. Benennung verbessern
Wichtig sind aussagekräftige Variablen- und Funktionsnamen. Wenn Sie Ihren Code nach einiger Zeit erneut aufrufen, helfen Ihnen klare Namen, den Ablauf zu verstehen, ohne alles neu lernen zu müssen.

5. Duplikate reduzieren
Wenn Sie Code kopieren und einfügen, ist das ein Zeichen dafür, dass Sie von gemeinsam genutzten Funktionen oder Klassen profitieren könnten. Duplikate erschweren die Wartung und kleine Änderungen können leicht zu Fehlern führen.

Commit und Push auf GitHub

1. Erstellen Sie einen Zweig
Ich habe damit begonnen, einen Zweig zu erstellen mit:

git checkout -b 

Dieser Befehl erstellt einen neuen Zweig und wechselt zu diesem.

2. Eine Reihe von Commits durchführen
Sobald ich mich im neuen Zweig befand, führte ich inkrementelle Commits durch. Jeder Commit stellt einen logischen Teil der Arbeit dar, sei es die Umgestaltung einer Funktion, die Behebung eines Fehlers oder das Hinzufügen einer neuen Funktion. Durch häufige, kleine Commits können Sie Änderungen effektiver verfolgen und den Verlauf des Projekts leichter überprüfen.

git status
git add 
git commit -m "Refactored function"

3. Neubasierung, um einen sauberen Verlauf zu behalten
Nachdem ich mehrere Commits durchgeführt hatte, habe ich meinen Zweig neu gegründet, um den Verlauf sauber und linear zu halten. Durch Rebasing kann ich Commits neu anordnen, kombinieren oder ändern, bevor sie an GitHub übertragen werden. Dies ist besonders nützlich, wenn einige der Commits sehr klein sind oder ich vermeiden möchte, den Commit-Verlauf mit zu vielen inkrementellen Änderungen zu überladen.

git rebase -i main

In diesem Schritt habe ich eine interaktive Rebase über dem Hauptzweig initiiert. Mit dem Flag -i kann ich den Commit-Verlauf interaktiv ändern. Ich könnte einige meiner kleineren Commits zu einem größeren, zusammenhängenden Commit zusammenfassen. Wenn ich zum Beispiel eine Reihe von Commits hätte wie:

Refactor Teil 1
Refactoring Teil 2
Fehler im Refactor

beheben

Ich könnte sie in einem einzigen Commit mit einer klareren Botschaft zusammenfassen

4. Änderungen an GitHub übertragen
Nachdem ich mit dem Commit-Verlauf nach dem Rebase zufrieden war, habe ich die Änderungen auf GitHub übertragen. Wenn Sie gerade einen neuen Zweig erstellt haben, müssen Sie ihn mit dem Flag -u in das Remote-Repository übertragen, wodurch der Upstream-Zweig für zukünftige Push-Vorgänge festgelegt wird.

git push -u origin 

5. Zusammenführen
Im letzten Schritt habe ich eine schnelle Zusammenführung zum Hauptzweig durchgeführt und erneut gepusht

git checkout main # change to the main branch
git merge --ff-only  # make a fast-forward merge
git push origin main # push to the main

Imbissbuden

Alles hat Raum für Verbesserungen. Refactoring mag mühsam erscheinen, führt jedoch häufig zu saubererem, besser wartbarem und effizienterem Code. Wenn Sie also das nächste Mal beim Refactoring zögern, denken Sie daran: Es gibt immer einen besseren Weg, Dinge zu erledigen.
Auch wenn ich denke, dass es jetzt perfekt ist, werde ich bei meinem nächsten Commit auf jeden Fall etwas verbessern können.

Freigabeerklärung Dieser Artikel ist reproduziert unter: https://dev.to/htsagara/refactoring-readMegenie-4816?1 Wenn es zu Verstößen kommt, wenden Sie sich bitte an [email protected], um ihn zu löschen.
Neuestes Tutorial Mehr>

Haftungsausschluss: Alle bereitgestellten Ressourcen stammen teilweise aus dem Internet. Wenn eine Verletzung Ihres Urheberrechts oder anderer Rechte und Interessen vorliegt, erläutern Sie bitte die detaillierten Gründe und legen Sie einen Nachweis des Urheberrechts oder Ihrer Rechte und Interessen vor und senden Sie ihn dann an die E-Mail-Adresse: [email protected] Wir werden die Angelegenheit so schnell wie möglich für Sie erledigen.

Copyright© 2022 湘ICP备2022001581号-3