1. はじめに
イントロダクション
プログラミングの学びを進めていくと、コードがシンプルだった初期段階から、次第にデータや処理が複雑化してくる場面に直面することがあります。特に、辞書を使ってデータを管理していると、最初は便利に感じても、だんだんとデータ構造が深くなり、可読性が低下してしまうことがあります。この時点で、「どうやって整理すればいいんだろう?」と悩む方も多いのではないでしょうか。
この記事では、初心者に向けて、辞書のようなシンプルなデータ構造から始め、問題が複雑化してきたときにクラスやヘルパークラスを使ってコードを整理し、保守しやすくする方法を段階的に解説します。コードがゴチャゴチャし始めたとき、どのようにしてリファクタリングを行い、シンプルさを保ちながらも機能を拡張できるか、その具体的な方法をお伝えします。
リファクタリングとは?
リファクタリングとは、プログラムの「外から見た動作」を変えることなく、内部のコードを整理して、より読みやすく、保守しやすくするための改善作業のことです。プログラムの動作には影響を与えないため、安心して行うことができますが、その効果は大きく、将来のコード変更や機能追加が簡単になります。また、リファクタリングを行うことで、バグの発生リスクを減らし、他の人がコードを理解しやすくすることもできます。
例えば、最初は辞書を使ってデータを管理していたのが、複雑な入れ子構造になり、コードの可読性が下がってきたとします。その場合、クラスやヘルパークラスを導入することで、データ構造を整理し、責任を分割してコードのメンテナンスをしやすくすることができます。この記事では、そういった状況に対処するためのリファクタリングの具体例も交えて、初心者でも実践しやすい方法を紹介していきます。
この記事で学べること
この記事では、Pythonの辞書やnamedtuple
、クラス、ヘルパークラスを使って、コードを段階的に改善していく方法を学びます。最初はシンプルな辞書からスタートし、データの複雑化に応じてクラスへとステップアップするプロセスを、実践的なコード例を通して解説します。また、リファクタリングの基本的な考え方と、その具体的な手順を学び、今後のプログラミングで役立つスキルを身につけることができます。
これから、コードをシンプルに進化させるためのステップを一緒に歩んでいきましょう!
プログラミングに興味があるけれど、何から始めればいいかわからない方に最適な一冊が「スッキリわかるPython入門 第2版」です。以下のポイントを参考にしてください。
本書の特徴とメリット
- シリーズ累計90万部突破
多くの読者に支持され、信頼されている大人気入門書の改訂版。 - 初心者でもわかりやすい解説
基本的な「コツ」を丁寧に説明し、迷わず学習を進められます。 - 実践的な「しくみ」の理解
プログラミングの基礎だけでなく、実際の開発に役立つ知識を習得可能。 - 「落とし穴」の回避
初心者が陥りがちな間違いをカバーし、安心して学習を進められる内容。
実際の読者の声
- 現役プログラミング教室の先生も推薦!
「この本を読んでPCスキルをマスターすれば、それでメシを食えますよ」という評価もあるほどの内容。面白くて勉強になるとの声が多い。
2. 辞書の基本とその限界
辞書の使い方
Pythonの辞書(dict
)は、データをキーと値のペアで管理するための非常に便利なデータ構造です。例えば、ユーザーの名前と購買情報を管理したい場合、辞書を使うことで簡単にデータを扱うことができます。
基本的な辞書の使用例
以下は、辞書を使ってユーザーごとの購買情報を管理する簡単な例です。
# ユーザーの購買情報を辞書で管理
user_purchases = {
"Alice": ["Laptop", "Mouse"],
"Bob": ["Keyboard"],
}
# Aliceの購買情報を取得
print(user_purchases["Alice"]) # ['Laptop', 'Mouse']
このように、辞書はユーザー名をキーとして、購買品目のリストを値として格納しています。辞書を使うことで、データの追加や取得が簡単に行えます。
辞書のメリット
- 柔軟なデータ管理: 辞書を使うと、動的にデータを追加したり、変更したりすることができます。例えば、ユーザーが増えても、新しいキーを追加するだけで対応できます。
- アクセスの速さ: 辞書はキーを使って値に直接アクセスできるため、データの検索が高速です。
辞書の限界
辞書はシンプルで使いやすいデータ構造ですが、次第に扱うデータが複雑化してくると、いくつかの問題が生じることがあります。特に、複数のデータを管理する際に「深い入れ子構造」になってしまい、コードの可読性が低下するリスクがあります。
複雑な入れ子構造の問題
例えば、ユーザーごとの購買情報だけでなく、各品目の価格やポイントを追加したい場合、次のように辞書の中にさらに辞書を入れる「入れ子構造」が必要になります。
# ユーザーごとの購買品目とその価格、ポイントを辞書で管理
user_purchases = {
"Alice": {
"Laptop": {"price": 1000, "points": 10},
"Mouse": {"price": 50, "points": 5}
},
"Bob": {
"Keyboard": {"price": 500, "points": 8}
}
}
# AliceのLaptopの価格を取得
print(user_purchases["Alice"]["Laptop"]["price"]) # 1000
このように辞書の中に辞書を入れることで、データをさらに細かく管理できますが、複雑化するリスクがあります。例えば、辞書のキーが間違っていた場合にエラーが発生しやすく、デバッグが難しくなります。また、構造が複雑になると、他のプログラマがコードを理解するのが難しくなり、保守性も低下します。
辞書を使い続けるリスク
- 可読性の低下: 入れ子構造が深くなると、コードを読んだときにデータの流れがわかりにくくなり、ミスを誘発しやすくなります。特に、他の開発者がコードを見たときに、データの構造を理解するのに時間がかかるでしょう。
- 保守性の低下: 複雑な辞書構造を使い続けると、後からデータ構造を変更したり、機能を追加する際に大規模な修正が必要になることがあります。これにより、バグが発生しやすく、コードのメンテナンスが難しくなります。
まとめ
辞書はシンプルで便利なデータ管理ツールですが、データが複雑化するにつれてその限界に直面することがあります。入れ子構造が深くなりすぎると、コードが読みづらく、保守が難しくなります。このような場合、次のステップとして「クラス」や「ヘルパークラス」を使ってデータ構造を整理する方法を検討する必要があります。次の章では、こうした問題に対処するために、namedtuple
やクラスを導入してコードを改善する方法を紹介していきます。
3. 複雑化を防ぐための選択肢:namedtuple
の導入
namedtuple
の基礎
辞書を使ってデータを管理していると、次第に複雑化してしまうことがあります。そんな時、クラスほどの柔軟性は必要ないけれど、シンプルにデータを整理したいという状況で活躍するのが、namedtuple
です。namedtuple
は、Pythonの標準ライブラリで提供されている軽量なデータコンテナで、タプルのように扱える一方で、フィールド名を持つことができるため、データへのアクセスが直感的で可読性も高くなります。
namedtuple
の使い方
例えば、ユーザーの購買データを管理する場合、以下のようにnamedtuple
を使ってデータ構造を定義することができます。
from collections import namedtuple
# Purchaseというnamedtupleを定義
Purchase = namedtuple('Purchase', ['item_name', 'price', 'points'])
# Purchaseオブジェクトを作成
purchase1 = Purchase('Laptop', 1000, 10)
purchase2 = Purchase('Mouse', 50, 5)
# フィールド名でアクセス可能
print(purchase1.item_name) # 'Laptop'
print(purchase1.price) # 1000
print(purchase1.points) # 10
namedtuple
を使うと、インデックスではなくフィールド名を使って値にアクセスできるため、コードが読みやすくなります。また、タプルと同様に不変であるため、データが変更されないことが保証されます。これにより、辞書のようにデータが誤って上書きされるリスクを減らすことができます。
namedtuple
の使いどころ
では、どのような状況でnamedtuple
を使うべきでしょうか?namedtuple
は次のような場合に適しています。
- クラスほどの柔軟性が必要ないとき:
namedtuple
はクラスほどのカスタマイズやメソッドの追加はできませんが、単にデータを保持する目的では十分な機能を提供します。例えば、ユーザーの購入履歴や商品の基本情報など、特定のフィールドを持つデータを保持する際に便利です。 - 軽量なデータ管理が必要なとき:
namedtuple
は非常に軽量です。オブジェクトの生成がクラスよりも高速で、メモリ消費も少なくて済むため、シンプルなデータ管理を行いたい場合に適しています。 - データの不変性が重要なとき:
namedtuple
は不変(イミュータブル)であるため、生成された後にデータが変更されることがありません。これにより、予期しないデータの変更を防ぎ、安全性が向上します。
実際の利用例
例えば、ユーザーの購買履歴をnamedtuple
で管理する場合、以下のように使うことができます。
# ユーザーの購買履歴をnamedtupleで管理
purchase1 = Purchase('Laptop', 1000, 10)
purchase2 = Purchase('Mouse', 50, 5)
# 購買履歴をリストに保存
user_purchases = [purchase1, purchase2]
# 購買履歴を表示
for purchase in user_purchases:
print(f"{purchase.item_name}: {purchase.price}円, ポイント: {purchase.points}")
このように、namedtuple
を使えば、辞書を使った複雑なデータ管理を避け、シンプルかつ軽量にデータを扱うことができます。
まとめ
namedtuple
は、クラスほどの柔軟性が必要ない場面で、軽量で直感的にデータを管理するための強力なツールです。特に、辞書を使うとデータ管理が複雑化しがちな場合、namedtuple
を使えばデータの構造を簡潔に保ちながら、安全にデータを保持できます。次の章では、データがさらに複雑になった場合に、クラスやヘルパークラスを導入してコードを整理する方法を紹介していきます。
4. 複雑な辞書からの脱却:クラスの導入
クラスを使うタイミング
プログラムがシンプルな段階では、辞書やnamedtuple
で十分にデータを管理できるかもしれません。しかし、データの管理が複雑化してくると、辞書やnamedtuple
では対応しきれなくなることがあります。例えば、辞書の入れ子構造が深くなり、データを管理するコードが増えてくると、どこで何を管理しているのかがわかりにくくなり、コードが読みづらくなります。また、データの操作に関するロジックが散在し始めると、ミスが発生しやすく、バグの原因にもなります。
このような状況になったとき、クラスを使ってコードを整理することを検討すべきタイミングです。クラスを導入することで、データの管理方法を整理し、コードの可読性を向上させ、保守性を高めることができます。また、クラスによってデータとそれに関連する操作を一つのまとまりとして扱うことができるため、複雑なロジックをスッキリさせることが可能です。
クラスの基本設計
クラスを導入することで、データのカプセル化と責任の分離を実現できます。これは、データとその操作を一つの単位にまとめ、外部から不必要な操作を防ぐとともに、各クラスが単一の責任を持つようにすることで、コードが分かりやすく、メンテナンスしやすくなります。
以下は、クラスを使ってユーザーの購買データを管理する例です。
クラスによるデータ管理の例
class Purchase:
def __init__(self, item_name, price, points):
self.item_name = item_name
self.price = price
self.points = points
def calculate_discount(self, discount_rate):
return self.points * discount_rate
class User:
def __init__(self, user_name):
self.user_name = user_name
self.purchases = []
def add_purchase(self, item_name, price, points):
purchase = Purchase(item_name, price, points)
self.purchases.append(purchase)
def calculate_total_discount(self, discount_rate):
total_discount = 0
for purchase in self.purchases:
total_discount += purchase.calculate_discount(discount_rate)
return total_discount
この設計では、Purchase
クラスが一つの購入データを管理し、User
クラスがユーザーごとの購買履歴を管理しています。これにより、データ管理の責任が明確に分かれており、コードの構造が整理されています。
クラスの利点
- データのカプセル化: クラスの属性(例:
item_name
,price
,points
)は外部から直接アクセスされることなく、クラス内で管理されます。これにより、データの安全性が向上し、意図しない変更が防がれます。 - 責任の分離:
Purchase
クラスは個々の購入データを管理し、User
クラスはユーザーごとの購入履歴を管理します。それぞれのクラスが特定の責任を持つため、コードの役割が明確になります。 - メソッドを使ったデータ操作: クラス内でデータに対する操作(例:
calculate_discount
メソッド)を定義することで、データとそれに関する処理が一緒に管理されます。これにより、コードの可読性が向上し、バグが発生する可能性が減少します。
クラス導入の結果
このようにクラスを導入することで、次のようなメリットが得られます。
- データ管理が明確になる: クラスを使うことで、データ構造が整理され、どのデータがどこで管理されているかが明確になります。
- コードが再利用しやすくなる: クラスにまとめたロジックは再利用がしやすくなり、同じ処理を複数箇所で書く必要がなくなります。
- コードの拡張が容易になる: 新しい機能を追加する場合でも、クラス内のロジックを変更するだけで済み、全体のコードに大きな影響を与えません。
まとめ
クラスを使うことで、データの管理が複雑化した場合でもコードを整理しやすくなります。特に、入れ子構造が深くなったり、データの操作が複雑になってきたと感じたら、クラスを使ってデータのカプセル化や責任の分離を行うことを検討しましょう。クラスの導入により、コードの可読性が向上し、保守性も高まります。次の章では、さらにクラスを進化させ、ヘルパークラスを使ってコードの整理を進める方法について解説します。
5. ヘルパークラスによるリファクタリング
ヘルパークラスとは?
プログラムがさらに複雑化してきたとき、クラスにまとめただけでは不十分な場合があります。特に、1つのクラスが多くの責任を持ちすぎている場合、コードが膨らみ、メンテナンスが困難になることがあります。そこで役立つのがヘルパークラスです。
ヘルパークラスとは、特定の責任を分離するために設計された補助的なクラスのことです。メインのクラスが持つ一部の機能を分担し、コードをより小さな部品に分けることで、各クラスが単一の責任に集中することができます。これにより、コードの保守性が向上し、新しい機能の追加や変更がしやすくなります。
ヘルパークラスを導入することで、次のようなメリットがあります。
- 責任の分離: 各クラスが特定の役割を果たし、それぞれの責任が明確になります。
- 拡張性の向上: ヘルパークラスを使うことで、新しい機能を追加する際に既存のコードを大きく変更せずに対応できるようになります。
- 再利用性: ヘルパークラスに分離したロジックは、他のクラスやプロジェクトでも再利用しやすくなります。
実践例
ここでは、すでに作成したUser
クラスとPurchase
クラスに対して、ヘルパークラスを使ってリファクタリングする例を紹介します。
まず、以前のコードでは、User
クラスが購入履歴の管理と割引計算の両方を担当していました。この状態では、クラスが持つ責任が多くなりすぎて、今後の拡張やメンテナンスが難しくなります。そこで、割引計算をヘルパークラスに分離してみましょう。
元のコード
class Purchase:
def __init__(self, item_name, price, points):
self.item_name = item_name
self.price = price
self.points = points
def calculate_discount(self, discount_rate):
return self.points * discount_rate
class User:
def __init__(self, user_name):
self.user_name = user_name
self.purchases = []
def add_purchase(self, item_name, price, points):
purchase = Purchase(item_name, price, points)
self.purchases.append(purchase)
def calculate_total_discount(self, discount_rate):
total_discount = 0
for purchase in self.purchases:
total_discount += purchase.calculate_discount(discount_rate)
return total_discount
このコードでは、User
クラスが購買履歴の管理と割引計算の両方を担当しています。ここで、割引計算を専用のヘルパークラスに分離してみます。
リファクタリング後のコード
class Purchase:
def __init__(self, item_name, price, points):
self.item_name = item_name
self.price = price
self.points = points
class DiscountCalculator:
def __init__(self, discount_rate):
self.discount_rate = discount_rate
def calculate(self, purchase):
return purchase.points * self.discount_rate
class User:
def __init__(self, user_name):
self.user_name = user_name
self.purchases = []
def add_purchase(self, item_name, price, points):
purchase = Purchase(item_name, price, points)
self.purchases.append(purchase)
def calculate_total_discount(self, discount_calculator):
total_discount = 0
for purchase in self.purchases:
total_discount += discount_calculator.calculate(purchase)
return total_discount
リファクタリングのポイント
DiscountCalculator
クラスの導入:DiscountCalculator
というヘルパークラスを導入し、割引計算の責任を専用のクラスに分離しました。これにより、User
クラスは購買履歴の管理に集中し、割引計算はDiscountCalculator
に任せられます。- クラスの責任の明確化: このリファクタリングにより、
User
クラスはユーザーの購買データを管理することに専念し、割引計算のロジックが外部に切り出されたことで、責任が明確に分かれました。 - 拡張性の向上: 今後、割引の計算方法を変更する必要がある場合、
DiscountCalculator
クラスだけを変更すればよく、User
クラスの変更は不要です。また、異なる計算方法のヘルパークラスを導入することも容易です。 - 再利用性の向上:
DiscountCalculator
クラスは、他のプロジェクトや他のユーザータイプの割引計算にも再利用できます。クラスの役割を分けることで、コードの再利用性が高まります。
以下は、先ほどのコードを実際に動かすための使用例です。この例では、ユーザーがいくつかのアイテムを購入し、そのアイテムに対して割引を計算します。
# クラスの定義 (省略)
# 例の使用コード
# ユーザーと購入品目の設定
user = User("Alice")
user.add_purchase("Laptop", 1000, 10) # Laptop: 1000円、10ポイント
user.add_purchase("Mouse", 50, 5) # Mouse: 50円、5ポイント
# 割引計算機の設定 (1ポイントあたり10円の割引)
discount_calculator = DiscountCalculator(10)
# 合計割引額の計算
total_discount = user.calculate_total_discount(discount_calculator)
# 結果の表示
print(f"{user.user_name}の合計割引額は {total_discount} 円です。")
結果
Aliceの合計割引額は 150 円です。
この例では、User
オブジェクトに複数の購入品を追加し、その後にDiscountCalculator
クラスを使って、各購入品に対する割引額を計算しています。最終的に、ユーザーの合計割引額が出力されます。
まとめ
ヘルパークラスを導入することで、コードがシンプルになり、各クラスが特定の責任に集中できるようになります。この結果、コードの保守性や拡張性が向上し、将来的な変更にも柔軟に対応できるようになります。特に、複雑なロジックや処理をヘルパークラスに分離することで、コードの整理が進み、ミスやバグの発生を防ぐことができます。
6. まとめ
要点の振り返り
この記事では、Pythonでのシンプルなデータ管理から始まり、コードが複雑化してきた場合の適切な対処法について段階的に解説しました。
最初に紹介した辞書は、シンプルなデータ構造であり、キーと値のペアでデータを管理するのに非常に便利です。しかし、辞書の入れ子構造が深くなるにつれて可読性や保守性が低下するという問題がありました。
次に、namedtuple
という軽量なデータコンテナを紹介しました。これはクラスほどの柔軟性が必要ない場面で役立ち、簡潔で変更不可能なデータ構造を提供しました。namedtuple
を使うことで、辞書の複雑さを回避しながら、直感的にデータへアクセスできるようになりました。
さらに、データ構造が複雑化した場合、クラスを導入するタイミングについて解説しました。クラスを使うことで、データのカプセル化と責任の分離が可能になり、コードが整理され、保守がしやすくなります。また、特定の処理をクラスにまとめることで、コードの再利用性や拡張性も向上します。
最後に、ヘルパークラスを導入することにより、コードの責任をさらに分離し、特定の処理をクラスごとに委任することで、コードの保守性をさらに高めました。これにより、複雑な処理が明確に分けられ、各クラスが特定の責任に集中できるようになりました。
プログラミングに興味があるけれど、何から始めればいいかわからない方に最適な一冊が「スッキリわかるPython入門 第2版」です。以下のポイントを参考にしてください。
本書の特徴とメリット
- シリーズ累計90万部突破
多くの読者に支持され、信頼されている大人気入門書の改訂版。 - 初心者でもわかりやすい解説
基本的な「コツ」を丁寧に説明し、迷わず学習を進められます。 - 実践的な「しくみ」の理解
プログラミングの基礎だけでなく、実際の開発に役立つ知識を習得可能。 - 「落とし穴」の回避
初心者が陥りがちな間違いをカバーし、安心して学習を進められる内容。
実際の読者の声
- 現役プログラミング教室の先生も推薦!
「この本を読んでPCスキルをマスターすれば、それでメシを食えますよ」という評価もあるほどの内容。面白くて勉強になるとの声が多い。
プログラミング教育において、多くの初学者が挫折する理由をご存じでしょうか?実は、それには多くの共通点があります。テックジムは、その問題点を深く理解し、20年以上にわたって蓄積してきた経験をもとに、誰もが安心して学べるプログラミング講座を提供しています。
テックジムは、ただの学習場ではありません。プログラミングを始めたい方や、より高いレベルに達したい方々に向けた、実践的な学びの場です。私たちが提供するカリキュラムは、初心者が直面する課題や躓きやすいポイントを徹底的に研究し、それを解決するためにデザインされています。
多くのプログラミングスクールが、フレームワークや複雑な技術から始めることで、学習者に過度な負担をかけ、結果として挫折を生む原因となっています。テックジムでは、まずは本当に重要な基礎からスタートすることで、無理なくスキルを積み上げていくことができます。例えば、関数やクラスといったプログラミングの核心部分をしっかりと理解し、それを使いこなすための時間を十分に確保しています。
これにより、受講生たちは無駄な混乱を避け、確実にスキルを身につけていくことができるのです。テックジムでの学びは、単なる知識の詰め込みではなく、実際に「できる」ことを目指した実践的なトレーニングです。
テックジムのPythonプログラミング講座は、経験と実績が詰まった講座です。初心者でも安心して参加でき、確実にステップアップできるこの講座で、あなたもプログラミングの世界に飛び込んでみませんか?
プログラミング学習に挑戦した多くの人が、途中で挫折してしまうことがあります。これは、難解なフレームワークや複雑な概念にいきなり取り組むことが主な原因です。しかし、テックジムではそのような挫折を未然に防ぐため、独自のカリキュラムを採用しています。
テックジムのカリキュラムは、まず基礎をしっかりと固めることから始めます。関数やクラスといったプログラミングの根幹をじっくり学ぶことで、無駄な負荷をかけずに確実にスキルを身につけることができます。このアプローチにより、学習者は「何をやっているのかわからない」という混乱を避け、自信を持って次のステップに進むことができます。
また、テックジムでは、段階的にスキルを積み上げることで、学習の進行に伴う負担を最小限に抑えています。その結果、無理なく、着実にプログラミングの世界で成功を収めることができるのです。
テックジムのプログラミング講座は、学ぶことの楽しさを実感しながら、挫折せずに成長できる最適な環境を提供します。
プログラミング学習において、最新技術の活用は欠かせません。テックジムでは、ChatGPTを用いた学習サポートを取り入れています。ChatGPTは、あらゆる質問に即座に答え、コードのバグ解決もスムーズにサポートします。これにより、効率的に学習を進めることが可能です。
しかし、テックジムの強みは、これだけではありません。どんなに優れたAIでも、人間のコーチによる個別サポートの価値は計り知れません。テックジムでは、経験豊富なプロのコーチがあなたの学習を支えます。プログラミングの基礎から応用まで、丁寧な指導と的確なフィードバックを提供し、あなたが抱える疑問や課題を一つ一つ解決していきます。
このように、最新の技術とプロのコーチングを組み合わせることで、テックジムでは、効率的でありながらも確実にスキルを身につけることができる学習環境を提供しています。
テックジムで学びながら、最先端のAI技術とプロの指導のベストな融合を体験してみませんか?
テックジムのPythonプログラミング講座は、その効果と実績で多くの受講生から高い評価を受けています。8月には180名を超える方々がこの講座にエントリーし、その人気と信頼の高さを証明しています。
この講座では、受講生が着実にスキルを身につけ、成長していることを実感できるカリキュラムを提供しています。プログラミングの基礎から実践的な応用まで、段階的に学べる内容は、初心者から経験者まで幅広く対応しています。また、学んだ知識をすぐに実践に移せる環境を整えており、学習の成果をリアルタイムで確認できるのも大きな特徴です。
テックジムの講座を受講した多くの方々が、「理解が深まった」「自信を持ってコードを書けるようになった」といった喜びの声を寄せています。これまでに培った経験と実績を活かし、受講生一人ひとりが成功への第一歩を踏み出せるよう全力でサポートしています。
あなたも、この成果を実感できるカリキュラムで、プログラミングスキルを確実に伸ばしてみませんか?
プログラミングに興味はあるけれど、いきなり本格的な学習に踏み出すのは少し不安…そんな方に最適なのが、テックジムの無料体験です。まずは気軽に始めてみたい、という方のために、テックジムではデモレッスンを提供しています。
この無料体験では、実際のカリキュラムの一部を体験し、学習の進め方や講師のサポートを実感することができます。受講前に「自分に合っているかどうか」を確認できるので、安心してスタートを切ることができます。
プログラミングが全く初めての方も、すでにある程度の経験を持っている方も、まずはこの無料体験で、テックジムの学びを体感してみませんか?今すぐ始める一歩が、あなたの未来を大きく変えるかもしれません。
無料体験は随時開催中です。ぜひこの機会に、新たなスキルを手に入れるための第一歩を踏み出してみてください!