Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Python でファクトリメソッド?
Search
kosuke naito
August 03, 2024
Programming
0
34
Python でファクトリメソッド?
Python でファクトリメソッド?を使った開発を行なって学んだことを発表しました。
kosuke naito
August 03, 2024
Tweet
Share
More Decks by kosuke naito
See All by kosuke naito
V が名前に入ってる
kosuke222naito
0
52
Other Decks in Programming
See All in Programming
Итераторы в Go 1.23: зачем они нужны, как использовать, и насколько они быстрые?
lamodatech
0
1.3k
Jaspr Dart Web Framework 박제창 @Devfest 2024
itsmedreamwalker
0
140
Go の GC の不得意な部分を克服したい
taiyow
3
990
KubeCon + CloudNativeCon NA 2024 Overviewat Kubernetes Meetup Tokyo #68 / amsy810_k8sjp68
masayaaoyama
0
290
見えないメモリを観測する: PHP 8.4 `pg_result_memory_size()` とSQL結果のメモリ管理
kentaroutakeda
0
900
情報漏洩させないための設計
kubotak
5
1.2k
命名をリントする
chiroruxx
1
570
Scalaから始めるOpenFeature入門 / Scalaわいわい勉強会 #4
arthur1
1
390
AppRouterを用いた大規模サービス開発におけるディレクトリ構成の変遷と問題点
eiganken
1
410
MCP with Cloudflare Workers
yusukebe
2
270
競技プログラミングへのお誘い@阪大BOOSTセミナー
kotamanegi
0
390
iOS開発におけるCopilot For XcodeとCode Completion / copilot for xcode
fuyan777
1
1.2k
Featured
See All Featured
How to Ace a Technical Interview
jacobian
276
23k
Being A Developer After 40
akosma
89
590k
Six Lessons from altMBA
skipperchong
27
3.5k
4 Signs Your Business is Dying
shpigford
182
21k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
33
2k
For a Future-Friendly Web
brad_frost
176
9.5k
Speed Design
sergeychernyshev
25
720
The Cult of Friendly URLs
andyhume
78
6.1k
GraphQLの誤解/rethinking-graphql
sonatard
68
10k
Large-scale JavaScript Application Architecture
addyosmani
510
110k
Raft: Consensus for Rubyists
vanstee
137
6.7k
It's Worth the Effort
3n
183
28k
Transcript
Python でファクトリメソッド? ナイトウ Press Space for next page 8/5/2024, 6:54:18
AM
このスライドはこちらで https://kosuke222naito.github.io/20240803-lt/
旧 Twitter GitHub Zenn Table of Contents 1. Python でファクトリメソッド?
2. Table of Contents 3. 自己紹介 4. ファクトリメソッド 5. Python での例 6. ファクトリメソッドを採用した経緯 7. 実際の使用例(チャットbot) 8. ファクトリメソッドを採用してみての感想 9. まとめ
旧 Twitter GitHub Zenn I'm ナイトウ Python で Web バックエンド
Web フロントもやりたい Vue が好き since: 2021 (4年目) 駆け出しエンジニア? (非 CS 専攻) 柏 (東葛dev 運営?) 自作キーボード 新本格ミステリ エヴァ、シュタゲ 元ハロヲタ (until: 2022)
ファクトリメソッド
ファクトリメソッド #とは 他のクラスのコンストラクタをサブクラスで上書き可能な自分のメソッドに置き換えることで、 アプリケーションに特化したオブジェクトの生成をサブクラスに追い出し、クラスの再利用性を高めることを目的とする Factory Method パターン - Wikipedia クラス図
Animal +String name +String sound() Dog +String name +String sound() : "bark" Cat +String name +String sound() : "meow" AnimalFactory +createAnimal(type: String) : Animal
ファクトリメソッドのいいところ 1. 再利用性の向上 2. 変更の容易さ 3. 可読性の向上
Python での例 1 from abc import ABC, abstractmethod 2 3
class Animal(ABC): 4 @abstractmethod 5 def __init__(self, name): 6 self.name = name 7 8 @abstractmethod 9 def speak(self): 10 pass 11 12 class Dog(Animal): 13 def __init__(self, name): 14 super().__init__(name) 15 16 def speak(self): 17 return "Woof!" 18 19 class Cat(Animal): 20 def __init__(self, name): 21 super().__init__(name) 22 23 def speak(self): 24 return "Meow!" 37 dog = AnimalFactory.create("dog", "Buddy") 38 cat = AnimalFactory.create("cat", "Whiskers") 26 class AnimalFactory: 27 @staticmethod 28 def create(animal_type, name): 29 if animal_type == "dog": 30 return Dog(name) 31 elif animal_type == "cat": 32 return Cat(name) 33 else: 34 raise ValueError("Unknown type") 35 36 39 40 print(dog.speak()) # "Woof!" 41 print(cat.speak()) # "Meow!"
None
ファクトリメソッドを採用した経緯 現在チャットbotを利用したアプリを作成中(PoC) 外部のAPIサービスを利用して実現する必要がある しかしサービス選定の時間はない そこで利用するサービスに依存せず コードの変更を簡単にしたい
実際の使用例(チャットbot) インターフェース(抽象基底クラス)の定義 10 class ChatBotServices(Enum): 11 OPENAI = "openai" 1
from abc import ABC, abstractmethod 2 from enum import Enum 3 4 class ChatBot(ABC): 5 @abstractmethod 6 def genrerate_response(self, messages) -> str: 7 pass 8 9
実際の使用例(チャットbot) 具象クラスの作成(OpenAI API) 7 def genrerate_response(self, messages) -> str: 8
completion = self.chatgpt_client.chat.completions.create( 9 messages=messages, 10 model="gpt-4o", 11 ) 12 content = completion.choices[0].message.content 13 14 return content 1 from openai import OpenAI 2 3 class OpenAIChatBot(ChatBot): 4 def __init__(self): 5 self.chatgpt_client = OpenAI(api_key=OPEN_AI_API_KEY) 6
実際の使用例(チャットbot) ファクトリ https://zenn.dev/miyaji26/articles/fe4a50319ed799 17 ChatBotFactory.register(ChatBotServices.OPENAI)(OpenAIChatBot) 1 class ChatBotFactory: 2 _class:
dict[str, type[ChatBot]] = {} 3 4 @classmethod 5 def register(cls, chat_bot_service: ChatBotServices): 6 def wrapper(cls_): 7 cls._class[chat_bot_service.value] = cls_ 8 return cls._class[chat_bot_service.value] 9 10 return wrapper 11 12 @classmethod 13 def get_chat_bot_class(cls, chat_bot_service: ChatBotServices): 14 return cls._class[chat_bot_service.value] 15 16
実際の使用例(チャットbot) デコレータとして from openai import OpenAI class OpenAIChatBot(ChatBot): def __init__(self):
self.chatgpt_client = OpenAI(api_key=OPEN_AI_API_KEY) def genrerate_response(self, messages) -> str: completion = self.chatgpt_client.chat.completions.create( messages=messages, model="gpt-4o", ) content = completion.choices[0].message.content return content
実際の使用例(チャットbot) ファクトリでインスタンスを作成 1 ChatBotClass = ChatBotFactory.get_chat_bot_class(ChatBotServices.OPENAI) 2 chat_bot = ChatBotClass()
これがやりたかった 柔軟に使うサービスを選択できる 4 ChatBotFactory.register(ChatBotServices.MICROSOFT_BING)(MicrosoftBingChatBot) 1 ChatBotFactory.register(ChatBotServices.OPENAI)(OpenAIChatBot) 2 ChatBotFactory.register(ChatBotServices.CLAUDE)(ClaudeChatBot) 3 ChatBotFactory.register(ChatBotServices.GOOGLE_GEMINI)(GoogleGeminiChatBot)
ChatBotClass = ChatBotFactory.get_chat_bot_class(ChatBotServices.OPENAI) chat_bot = ChatBotClass() chat_bot_response = chat_bot.generate_response(messages) 1 2 3
ファクトリメソッドのあんまりよくないところ 使わない場合に比べてコードが複雑(難解)になる
補うために ドキュメントを作成 ペアプロ ドキュメントレビューでメンバーを巻き込む 1 # chat-app 2 3 ##
基本設計方針 4 5 利用する外部APIがまだ決まっていないのでファクトリメソッドに 6 抽象クラス(インタフェース)を各サービスの外部APIを用いて実装 7 呼び出し元でどのサービスを利用するかを決める。 8 9 ## ディレクトリ構成 10 11 `tree.txt` を参照 12 13 ### `services` ディレクトリ 14 15 ビジネスロジックなどを担う 16 17 - `chat` 18 19 - AI チャットサービス(Open AIなど)を利用したチャット生 20 - ChatGPT が苦手な最新情報(天気情報など)の取得を別の外部 21 22 - `geocoding` 23 24 - ジオコーディング処理を担う 25 - あくまでも関数としてのふるまいまでにとどめる
None
ファクトリメソッドを採用してみての感想 😇 過剰だったかもしれない 📕 ドキュメントの作成を丁寧に行う必要があった 🙋♂️ この作りにしたおかげで他メンバーへの引き継ぎスムーズにできた 🤔 コンストラクタで異なる引数を受け取る場合 🤫
Python の理解も足りてない 😵💫 果たしてこれは本当にファクトリメソッドだったのか
まとめ ファクトリメソッド: オブジェクトの生成をサブクラスに追い出し、クラスの再利用性を高める ファクトリメソッドを使うべき状況 オブジェクトの生成方法が複雑な場合 生成するオブジェクトの種類が増減する可能性がある場合 生成ロジックをカプセル化したい場合