MOBILUS TECH BLOG

モビルスのプロダクト開発を支えるメンバーが 日々の開発現場の情報を発信します。

AWSのSSM パラメータストアを一発でCSV出力する方法

Written by Tomotaka Miyauchi

9月に入ってもまだまだ暑いし夏だなぁ〜、と思っていたら急に秋になりましたね。
どうも、SaaS Product Divisionの宮内です。

背景

この前、AWS SSM パラメータストアの値を整理しようと思い立ちました。

登録済みのパラメータ一覧が欲しくなりましたが、コンソール上から拾ってくるのはエンジニアらしくないので、AWS CLIを使って一覧をズバッと取得しようと思いました。

ただ、意外とネット上にドンピシャの答えがなかったので、(GitHub Copilot Chatに助けを借りながら)これが最適解かな、と思うコマンドを導き出したので紹介します。

コマンド

最初に結論です。ドンッ

$ export AWS_PROFILE=dev
$ aws ssm get-parameters-by-path --with-decryption --path "/" --recursive --query "Parameters[?contains(Name,'develop')].{Name:Name,Value:Value}" | jq -r 'sort_by(.Name) | .[] | [.Name, .Value] | @csv' > parameter_store.csv

このコマンドでは、AWS Systems Managerのパラメータストアにある全てのパラメータのうち、名前に"develop"が含まれるものを抽出しています。 暗号化されているパラメータもデコードして出力します。

また、パラメータの名前を"/[製品名]/[環境名]"のようにサブディレクトリで定義している場合は、以下のコマンドでも取得可能です。

$ export AWS_PROFILE=dev
$ aws ssm get-parameters-by-path --with-decryption --path "/[製品名]/[環境名]/" --recursive --query "Parameters[].{Name:Name,Value:Value}" | jq -r 'sort_by(.Name).[] | [.Name, .Value] | @csv' > parameter_store.csv

では、解説していきます。

前提条件

  • 実行環境はMacです。
  • jqをインストールしておきます。※
  • AWS CLI v2をインストールしておきます。
  • AWS CLI v2のプロファイルを設定しておきます。(AWS_PROFILE=devの部分を指します)

    jqはコンソール上でJSON形式を加工するためのパッケージです。Macの場合、Homebrewからもインストールできます。

    $ brew install jq
    $ jq -V
    

解説

大枠のつくり

パイプラインで繋がっているだけで、このコマンドは次のように分解することができます。

  1. AWS CLIでパラメータストアからパラメータを抽出します。
  2. 抽出したデータをjqコマンドで JSON → CSV の形式へ変換します。
  3. 変換したCSVをファイルに出力します。

具体的には以下の通りです。

$ aws ssm get-parameters-by-path --with-decryption --path "/" --recursive --query "Parameters[?contains(Name,'develop')].{Name:Name,Value:Value}"

で、AWS CLIを使ってパラメータストアのデータをjson形式で取得し、

$ jq -r 'sort_by(.Name) | .[] | [.Name, .Value] | @csv' [前段パイプラインの出力結果]

で、jqを使ってCSVの形式に編集し、

$ [出力結果] > parameter_store.csv

で、編集したCSVの内容をファイルに出力します。

1. パラメータの抽出

$ aws ssm get-parameters-by-path --with-decryption --path "/" --recursive --query "Parameters[?contains(Name,'develop')].{Name:Name,Value:Value}"
[
    {
        "Name": "/myapp/develop/config",
        "Value": "some-value"
    },
    {
        "Name": "/myapp/develop/secret",
        "Value": "another-value"
    }
]
  • aws ssm get-parameters-by-path

    パラメータストアからパラメータを取得します。 get-parameters-by-pathは、指定されたパス以下のすべてのパラメータを取得するためのサブコマンドです。

  • --with-decryption

    暗号化されたパラメータの値をデコードして取得します。

  • --path "/"

    取得するパラメータのパスを指定します。サブディレクトリを指定する場合は、こちらに設定します。

  • --recursive

    指定されたパス以下のすべてのパラメータを再帰的に取得します。これにより、サブディレクトリ内のパラメータも含まれます。

  • --query "Parameters[?contains(Name,'develop')].{Name:Name,Value:Value}"

    aws ssm get-parameters-by-pathで取得されるデータは以下のフォーマットです。
    そのため、Parameters属性に対してクエリを実行します。

    {
      "Parameters": [
          {
              "Name": "/myapp/develop/config",
              "Type": "String",
              "Value": "some-value",
              "Version": 1,
              "LastModifiedDate": 1530018761.888,
              "ARN": "arn:aws:ssm:us-east-1:111222333444:parameter/site/newyork/department/marketing"
          },
          {
              "Name": "/myapp/develop/secret",
              "Type": "String",
              "Value": "another-value",
              "Version": 1,
              "LastModifiedDate": 1530018823.429,
              "ARN": "arn:aws:ssm:us-east-1:111222333444:parameter/site/newyork/department/infotech"
          },
          ...
      ]
    }
    

    パラメータ名(.Name)に "develop" が含まれるものをフィルタリングします。フィルタリング結果から名称(.Name)と値(.Value)フィールドを抽出します。

2. CSV形式に変換

$ jq -r 'sort_by(.Name) | .[] | [.Name, .Value] | @csv' [前段パイプラインの出力結果]
"/myapp/develop/config","some-value"
"/myapp/develop/secret","another-value"
  • -r

    jqの出力を生の文字列(raw output)として表示します。引用符が取り除かれ、CSV形式の出力が得られます。

  • sort_by(.Name)

    JSONデータをNameフィールドに基づいてソートします。

  • .[]

    ソートされた配列の各要素に対して処理を行います。以下のように配列の1要素ごとに以降の処理を行います。

    {
      "Name": "/myapp/develop/config",
      "Value": "some-value"
    }
    {
      "Name": "/myapp/develop/secret",
      "Value": "another-value"
    }
    
  • [.Name, .Value]

    各要素のNameとValueフィールドを抽出します。これは、配列の各要素から特定のフィールドを選択するためのフィルタです。

  • @csv

    抽出したフィールドをCSV形式に変換します。

3. ファイルに出力

$ [出力結果] > parameter_store.csv

変換した結果をCSVファイルに出力します。
標準出力をファイルに出力する、お馴染みのコマンドですね。

おまけ

このコマンドをそのまま使うことはないと思います。

実行して「動かない?」場合は、aws ssm get-parameters-by-path 〜の部分だけを実行して、コンソール上にJSON形式で出力されることを確認しましょう。

モビルスでは、一緒に働く仲間を募集中です!
興味のある方は、ぜひ採用情報のページをご覧ください!

育休で気が付いたらQAしていた件

はじめまして、モビルスで品質保証を担当しているQA Section所属の倉持です。

モビルスでは女性・男性共に育児休業(以降、育休)を取得することが可能です。 社内ではライフステージの変化を迎える方も増えてきていて、 今秋以降も複数の男性メンバーが育休取得予定。

自分も昨年子供が生まれたので、この度育休を取得しました。
今回は育休で感じたことや実体験を男性側の視点でお届けします。
タイトルは最後にえいやー!で回収します。笑

1.背景

取得理由

育休を取った理由はざっくり以下になります。

  • なんとなく取るものだと思っていた
  • 世の中的にはまだ男性の取得が目立っていない印象
  • 自分の友人らが取得していて、「よかった!」というのを聞いていた

まず取得する際、当時の上長に相談したところ
「休みではないからね~。実際休む暇はないと思うけれど★」みたいなことを言われた記憶があります。
今思うと、本当にその通りで休みはないです...が、それ以上に子の成長を
日々実感できるのが何よりも大きいです。

育休・子育ての前提としては妻側を「手伝う」ではなく、お互いが「主体」の立場
だといい流れを作ることができる気がします。

取得期間

2024年3月頃~2024年7月31日
大体4か月ほど取得しました。

書類関連

育休を取得するにあたってたくさんの書類提出が控えています。
思ったより時間がかかったので大変でしたが、社内Wikiや人事の方のフォローもあり
特に問題はありませんでした。
ただ、ご自身でも調べておくことを推奨します。笑
例)育休の条件、育休中の手当

引継ぎについて

育休前最終日はバタついたもののチームへ引継ぐ情報は前々から
整理できていたので、早めに相談してよかったと思ってます。

また、見込みでいいので復帰後の大体のタスクも記載しておくと、後々スムーズです👍
自分の場合メモを残しておいたので、よかったと感じています。

2.育休スタート ~3・4月編~

まずは覚える

初日からすぐに、修業期間として1週間ほどワンオペでやってみました。笑
当時の1日のスケジュールは大体以下です。

時間 やること 所感
7:00~9:00 ミルク・おむつ替え 朝一は吐き戻しが多いので注意
12:00前後 ミルク・おむつ替え お昼食べたい・・・
15:00~16:00 お風呂・ミルク・おむつ替え 準備であたふた&自分たちの夕食も準備
19:00~20:00 ミルク・おむつ替え 自分もお風呂入りたい・・・
23:00前後 ミルク・おむつ替え ここで吐き戻しあると大変
2:00~5:00 ミルク・おむつ替え 場合によってはもう寝ることは不可

ミルク・おむつ替え後の各間、寝てくれると他のことができるのですが
各間でかなり差があったと思います。また、他のこと、といっても次やることの
準備でほぼ終わっていた記憶があります。笑
ミルクやおむつ替えといっても、実は細かい工程がいくつもあることを知りました🧐

この時期の具体的な成長としては首がまだ据わりかけでしたが、嬉しさの感情が
出てきたのかニコニコしてくれました。

<4月頃>

修業後

大分鍛えられたのか、1人でもこなせるようになりました。
今後の担当について妻と話し合った結果、以下のように割り振ることにしました。
もちろん、子供のことで何か気がついた時はお互い担当関係なく、やるようにしてました。

  • 1日ずつ下記の①と②を交代していく
    • ①おむつとミルク担当、②その日の夕食、お風呂担当
  • 友人に会う等の外出予定がある時
    • 例)出かける側が①を事前に2日連続でやり、残る側が当日1人でやりきる

3.うまくはいかない時もある~5・6・7月編~

離乳食がスタート

5月くらいからは離乳食が始まりました。
大分余裕が出てきたものの...やはり準備・計画が大事だと実感しました。

時間 やること 所感
7:00~9:00 ミルク・おむつ替え・離乳食 食べる量間違えないように
~11:00前後 お散歩 近所を歩いたり、雨の日は絵本を読む
12:00前後 ミルク・おむつ替え ここで寝てくれるとその後動きやすい
15:00~16:00 お風呂・ミルク・おむつ替え お風呂は好きみたいで機嫌はよかった
19:00~20:00 ミルク・おむつ替え ミルク前後で泣くことが多かった時間帯
23:00前後 ミルク・おむつ替え スヤスヤタイムに入れば...🙌

離乳食はアレルギーとかあるので慎重に進めました。
7月頃からは2回食にして、お昼にも離乳食を与えていました。
具体的な成長についてはハイハイしたり、つかまり立ちしたり...等で
考えることがより増えた時期でもありました。

<7月頃>

定着はしたものの...

流れがルーティン化してきて、気分転換に趣味の陸上の練習・記録会に出ていました。
ただ、どうしても寝かしつけがうまくいかない時が多く、悩んだ時期でもありました😔

特に6月頃からは暑くなってきて、以下のようになってしまいました。

  1. 泣いたので抱っこしてみる
  2. 密着するのでお互い暑い ※赤ちゃんの体温は元々が高いため汗をかきやすい
  3. 暑いせいか余計泣く
  4. 一度床に置いてみる
  5. (以下ループ...)

このようにどうしようもない時もあるので、精神論でなんとかやってました。笑
とはいえ寝顔を見てからは不思議とがんばれた気がします!

4.復帰してみて~子の成長と時の流れは早い~

気が付いたらもう8月

本当にあっという間に月日は流れて、気が付いたら約4か月間の育休が終了していました。
むしろ、もう少し長く育休を取得してもよかったかもしれません。笑

振り返ってみると育休開始時は本当にバタバタして実はもう記憶がほぼないくらいです。
成長具合で言うと、寝返りができたかどうかくらいだったと思います。
ですが、今はつかまり立ちをしたり、後追いされたりで、毎日成長しているんだな~
と感じています。自分はもう退化する一方なのに...。笑

いろいろありましたが8月1日に無事に復帰できました🙌
初日は久々のオフィスで少し懐かしさもありつつ、チームメンバーや他部署の方も
元気に迎えてくれてとても安心感がありました。

5.最後に

子育てはまるでQAの活動みたいでした

結果的に育休は取得してよかったです。普段と今後の生活の見直しにもなりました。
子育ては振り返ってみると、これまで普段やってきたQA活動のように感じました。

子育て QA活動
お風呂、離乳食等の準備 テスト計画、テスト観点出し
ミルク量や離乳食の種類を考えて調整する テストケース数見積り、作成、追加
ミルクや離乳食を与える、おむつを替える テスト実行
お昼寝や睡眠・笑顔等日々の成長 無事リリース、お疲れさまでした
- 振り返りしつつ、改善点を次回実践する。

なんとなくですが、全体的に流れが決まってくるとリグレッションテスト※1を
やっているような感じになりました。笑
ただ、難しいのが手順や期待値に決まりはなく、何か問題があった時は自身の
「改善」として捉えていく必要があると考えています。

…そんなわけで子育てはQA(以下略、ここでタイトル回収)。笑

最後になりますが、育休に関してご理解くださった会社・部署・チームメンバーには
改めて感謝しております。ありがとうございました🙇

育休は取れる時に取っておくと、後々自分にとってもプラスになるのかなと思うので
迷っている方はぜひ相談・取得してみてほしいです。

育休に対してはキャリアへの不安もあるかもしれませんが、むしろ見つめ直すいい機会でもあります。
世の中的にはまだまだ男性の育休取得率は決して高くはないかもしれません。
近い将来、今よりも増えているといいな~と感じています。

以上になります。
ここまで読んでいただいた方、ありがとうございました。

※1…「回帰テスト」とも呼ばれる。今回は本題と異なるので正しい定義は省きますが、ここでは「新しいことを追加しても、大体同じ流れで
繰り返し実行して、いつも通り問題ないよね」くらいのイメージで捉えてもらえると幸いに存じます。

モビルスでは、一緒に働く仲間を募集中です! 興味のある方は、ぜひ採用情報のページをご覧ください!

AWS JumpStart 2024 参加レポート

8月6~7日に開催された「AWS JumpStart 2024」へモビルスからもエンジニア4名が参加しました。 

今回はSaaS Product DivisionでMOBI VOICEの開発を行っているプラディープ さんの参加レポートをお届けします。

※原文は英語ですが日本語版のリクエストもあったため、後半に翻訳文を貼り付けしています。

What is AWS JumpStart

AWS JumpStart offers a two-day workshop program designed to enhance your understanding of AWS and your architectural design skills. The program includes preparatory learning, hands-on exercises, team discussions, and presentations.

Prerequisites

I am already an AWS Certified Solutions Architect – Associate, so I took the AWS Skill Builder refresher course before starting the AWS Jumpstart workshop.

AWS Skill Builder - AWS Technical Essentials Summary

The course is divided into six modules:

  1. Introduction to Amazon Web Services
  2. AWS Compute
  3. AWS Networking
  4. AWS Storage
  5. Databases on AWS
  6. Monitoring, Load Balancing, and Scaling

During the course, I created an employee directory application that stores images and information about fictional employees using the following AWS services:

  • AWS IAM (Identity and Access Management)
  • Amazon S3
  • Amazon CloudWatch
  • Amazon DynamoDB
  • Amazon EC2
  • Amazon RDS

Tools Used in  the AWS Jump session

  1. Slack
  2. Zoom
  3. Mira
  4. AWS

Schedule

Day 1 : 6th Aug 2024 

The session covered the basics of web application development, hands-on development with EC2 instances, and the creation of a Todo application.

Hands On Session - Application development of ToDo 

Steps to develop the Todo application

  1. Create VPC/Security group
    1. Create VPC
    2. Create 3 Security group for alb,web,db
  2. Creation of Aurora MySQL 
  3. Creation of ALB
  4. Creation of ECS

Final Architecture of the ToDo application

Final View in the browser

Summary of day 1 

During the development of the to-do application, I learned about the development of VPC, ALB, AuroraDB, ECS, CloudWatch, and AWS Fargate. While creating the ALB, I made a mistake in assigning subnet groups. After debugging for a while, I was able to rectify the error. In Slack, there was a channel called bedrocks-questions, which was linked to the Bedrock generative AI. We posted our questions there, and the AI provided answers. I found this really helpful during the session because it allowed us to get answers without disturbing the presenter.

Day 2 : 7th Aug 2024 

Quiz 

The session was conducted via Zoom, and it was interesting to see nearly 180+ members participating live. 

Architecture Design Challenge(Unicorn EC Site development)

Overview

  • You will join Unicorn Relations LLC as new employees, and you will be divided into teams to design the architecture for a given service.
  • During the process, three teams will be randomly selected to present their architecture.

Objectives

  • Gain practical experience by designing and visualising the architecture of a service using AWS services.
  • Deepen your understanding of trade-offs and characteristics of various services during the architecting process

Requirement :

Scale

  • User Count: Tens of thousands
  • Peak Hours: Evenings in Japan
  • Service Area: Japan
  • Platform: Web

Required Features

  • Product listing page
  • Product details
  • Product images
  • Cart and purchase functionalities
  • Payment, inventory management, and delivery systems will utilize external SaaS APIs
  • Account management functionality

System Requirements (modifiable)

  • Backend: Java/Spring Boot
  • Frontend: TypeScript/React
  • Database: MySQL
  • Local development is using Docker, but containers are not mandatory

Outline of My architecture

During the morning session, the architecture development was done individually. Based on the information learned on Day 1, I created the diagram below:

Summary of my creation

The architecture depicted in the diagram is designed for a scalable web platform serving tens of thousands of users, primarily active during peak hours in the evenings in Japan. It includes the following key components:

  • User Access: Amazon Route 53 for DNS, Amazon CloudFront for CDN, and S3 for static content.
  • Compute: EC2 instances within a VPC across multiple availability zones for high availability, managed by Elastic Load Balancing.
  • Data Storage: Amazon Aurora for database needs, ensuring read and write scalability.
  • Monitoring: Amazon CloudWatch for monitoring and logging.
  • Backend and Frontend: AWS Lambda and API Gateway for serverless backend interactions, utilizing external APIs for payment, inventory, and delivery. Frontend built with TypeScript/React.
  • Account Management: Amazon Cognito.
  • Notifications: Amazon SNS.

This setup ensures scalability, high availability, and efficient handling of user interactions and transactions.

In the group work session, the team was divided into groups of 4 members, each with an AWS mentor. 

During the Zoom breakout room discussion of my architecture, the engineer provided various feedback about my design.

The provided architecture is robust and well-suited for a high-traffic e-commerce platform in Japan, ensuring scalability, high availability, and performance. However, some improvements can be made:

  • Incorporate Auto Scaling Groups for EC2 instances to handle varying loads more efficiently.
  • Utilize RDS Proxy to optimise database connections and improve Aurora's performance.
  • Implement AWS WAF for enhanced security against web attacks.
  • Leverage Amazon S3 Transfer Acceleration for faster global content delivery.
  • Consider using AWS Fargate for container orchestration to reduce management overhead and improve scalability.

These enhancements will further optimise the system's reliability, security, and performance.

After the group discussion, we collaboratively developed the architecture below and presented it to the AWS members. We received valuable feedback on our design.

Assumptions and Future Improvement Opportunities for the above architecture 

Assumptions

  • Using Docker, ECS (Elastic Container Service) is adopted.
  • WAF (Web Application Firewall) is used for security.

Future Improvement Opportunities

  1. Expansion to Overseas Markets:
    • Load balancers can be used to distribute traffic globally.
  2. Operating with Microservices:
    • Transitioning to a microservices architecture for better scalability and maintainability.
  3. Adopting NoSQL Databases:
    • Utilizing NoSQL databases for their scalability, flexibility, and performance advantages, making them suitable for an e-commerce site.

Summary of the Architecture

The application, designed for a web platform with tens of thousands of users primarily active during Japan's evening hours, leverages a robust architecture hosted on AWS Cloud. Key components include:

  • Frontend: TypeScript/React application.
  • Backend: Java/Spring Boot services.
  • Database: MySQL on Amazon RDS.
  • Caching: Amazon ElastiCache.

Features:

  • User Functionality: View product lists, detailed information, images, and manage cart and purchases.
  • External Integrations: Payment, inventory, and shipping functions via SaaS APIs.
  • Authentication: Managed by Amazon Cognito.
  • Storage and Delivery: Managed by Amazon S3 and CloudFront.

Infrastructure:

  • Container Management: ECS with Fargate for scalable container orchestration.
  • Networking: VPC with public and private subnets across multiple availability zones, utilizing NAT and Internet Gateways.
  • CI/CD: Automated with AWS CodePipeline, CodeBuild, and CodeDeploy, integrated with GitHub.
  • Asynchronous Communication: SQS and Lambda.
  • Monitoring: CloudWatch for performance tracking.

This architecture ensures high availability, scalability, and efficient resource management to meet user demands effectively.

Finally overall feedback about the AWS Jump Start 

In the architecture review, all team members came from different companies involved in app development. Since we typically focus on web applications related tasks, we were able to discuss both app and infrastructure perspectives, which brought refreshing insights from the app-side viewpoints.

Reaching a consensus was challenging when opinions diverged between the app and infrastructure sides; it felt like a personal challenge. Additionally, the hands-on experience with ECS was valuable, especially since I will be working with containers in my future role.

Reflecting on the overall experience, it was highly educational from a practical standpoint. While I had learned about AWS services through books and seminars, applying that knowledge fully in practice had been difficult. Participating in this workshop felt like moving to the next level, similar to stepping onto the court for the first time after practising dribbling, passing, and shooting.

For those with limited practical design experience, this workshop offers substantial learning opportunities. Conversely, if you have concerns about your knowledge, I recommend doing some preparatory learning to participate effectively in group discussions

--------------------------------------------------------------------------------------------------

AWS JumpStartとは?

AWS JumpStartはAWSの理解とアーキテクチャ設計スキルの向上を目的とした2日間のワークショッププログラムです。事前学習、ハンズオン演習、チームディスカッション、プレゼンテーションから構成されています。

事前学習

私はすでにAWS認定ソリューションアーキテクト – アソシエイト資格を持っているため、事前学習としてAWS Skill Builder - AWS Technical Essentialを受講しました。

AWS Skill Builder - AWS Technical Essentials 概要

このコースは6つの講座から構成されています

  1. Amazon Web Servicesの紹介
  2. AWSコンピューティング
  3. AWSネットワーキング
  4. AWSストレージ
  5. AWSのデータベース
  6. モニタリング、ロードバランス、スケール

コースの中では以下のAWSサービスを使用して従業員の画像と情報を保存する架空のディレクトリアプリケーションを作成しました

  • AWS IAM (Identity and Access Management)
  • Amazon S3
  • Amazon CloudWatch
  • Amazon DynamoDB
  • Amazon EC2
  • Amazon RDS

AWS Jump sessionの中で使用したツール

  1. Slack
  2. Zoom
  3. Mira
  4. AWS

スケジュール

Day 1 : 2024年8月6日

Day1では、Webアプリケーション開発の基本、ECS・Auroraを使ったTodoアプリケーションの作成について学びました。

ハンズオンセッション-ToDoアプリケーション開発

ToDoアプリケーション開発の手順

  1. VPC/セキュリティグループの作成
    1. VPCの作成
    2. ALB、Web、DB用の3つのセキュリティグループの作成
  2. Aurora MySQLの作成
  3. ALBの作成
  4. ECSの作成

最終的に作成したToDoアプリケーションのアーキテクチャ

ブラウザでの最終表示

Day1まとめ

ToDoアプリケーションの開発を通じてVPC、ALB、AuroraDB、ECS、CloudWatch、そしてAWS Fargateについて学びました。ALBを作成する際に、サブネットグループの割り当てでミスをしてしまいましたがデバッグを行い、エラーを修正することができました。

用意されたSlackには「bedrocks-questions」というチャンネルがあり、生成AIサービス「Amazon Bedrock」と連携していて、質問を投稿するとAIが回答を提供してくれます。この機能は発表を遮ることなく質問ができ回答を得られるので、非常に役に立ちました。

Day 2 : 2024年8月7日

クイズ

セッションはZoomで行われ、180人以上のメンバーがライブで参加していたのが印象的でした。

アーキテクチャ設計チャレンジ(ECサイト開発)

概要

  • ある会社へ入社した想定で、チームに分かれて指定されたサービスのアーキテクチャを設計する
  • ランダムに選ばれた複数のチームが自分たちのアーキテクチャを発表

目的

  • AWSサービスを使用してサービスのアーキテクチャを設計し、可視化することで実践的な経験を得る
  • アーキテクチャを設計する過程で、AWSサービスのトレードオフや特徴についての理解を深める

要件:

 

スケール

  • ユーザー数: 数万
  • ピーク時間: 日本の夕方
  • サービスエリア: 日本
  • プラットフォーム: Web

必要な機能

  • 商品一覧ページ
  • 商品詳細
  • 商品画像
  • カートと購入機能
  • 支払い、在庫管理、配送システムは外部のSaaS APIを利用
  • アカウント管理機能

 

システム要件(変更可能)

  • Backend: Java/Spring Boot
  • Frontend: TypeScript/React
  • Database: MySQL
  • ローカル開発にはDockerを使用していますが、コンテナの使用は必須ではありません

アーキテクチャの概要

午前中のセッションでは、アーキテクチャの設計を個別に行いました。Day 1で学んだ情報を基に、以下の図を作成しました。

作成内容の概要

図に示されたアーキテクチャは、数万のユーザーに対応するスケーラブルなWebプラットフォームを設計しており、主に日本の夕方のピーク時間帯に活発に使用されます。以下の主要なコンポーネントから構成されています:

  • ユーザーアクセス: Amazon Route 53でDNS管理、Amazon CloudFrontでCDN、S3で静的コンテンツを提供
  • 計算リソース: 高可用性のために複数のアベイラビリティゾーン内のVPCにEC2インスタンスを配置し、Elastic Load Balancingで管理
  • データストレージ: 読み書きのスケーラビリティを確保するためにAmazon Auroraを使用
  • 監視: Amazon CloudWatchで監視とログ収集を行う
  • BackendとFrontend: サーバーレスBackendのインタラクションにはAWS LambdaとAPI Gatewayを使用し、支払い、在庫、配送には外部APIを利用。FrontendはTypeScript/Reactで構築
  • アカウント管理: Amazon Cognito
  • 通知: Amazon SNS

このセットアップでは、スケーラビリティ、高可用性、そしてユーザーのインタラクションやトランザクションの効率的な処理を確保しています。

次に行われたグループワークセッションでは、チームが4人ずつのグループに分かれ、それぞれにAWSメンターが付きました。

Zoomのブレイクアウトルームでアーキテクチャを議論する中で、同じグループのメンバーから私が設計した内容について様々なフィードバックをもらいました。

フィードバックとしては、日本の高トラフィックなeコマースプラットフォームに適しており、スケーラビリティ、高可用性、パフォーマンスを確保しているが、以下の改善が挙げられました:

  • EC2インスタンスのオートスケーリンググループを導入し、変動する負荷により効率的に対応できるようにする
  • データベース接続を最適化し、Auroraのパフォーマンスを向上させるためにRDS Proxyを利用
  • Web攻撃に対するセキュリティを強化するためにAWS WAFを実装
  • グローバルコンテンツの配信を迅速にするためにAmazon S3 Transfer Accelerationを活用
  • コンテナオーケストレーションの管理負担を軽減し、スケーラビリティを向上させるためにAWS Fargateの使用を検討

これらの改善により、システムの信頼性、セキュリティ、パフォーマンスがさらに最適化されます。

グループディスカッションの後、グループで以下のアーキテクチャを開発しました。AWSのメンバーに向けて発表し、設計について貴重なフィードバックをいただきました。

上記のアーキテクチャに対する前提条件と将来的な可能性

前提条件

  • Dockerを使用し、ECS(Elastic Container Service)を採用
  • セキュリティにはWAF(Web Application Firewall)を使用

 

将来的な可能性

  • 海外市場への展開: 
      • ロードバランサーを使用して、トラフィックをグローバルに分散させることができる
  • マイクロサービスの導入:
  •  マイクロサービスアーキテクチャに移行することで、スケーラビリティとメンテナンス性を向上させることができる
  • NoSQLデータベースの採用: 
    • NoSQLデータベースを利用することで、スケーラビリティ、柔軟性、パフォーマンスの利点を活かし、eコマースサイトに適したシステムを構築できる

 

アーキテクチャのまとめ

このアプリケーションは、日本の夕方の時間帯に主にアクティブな数万人のユーザー向けのWebプラットフォームとして設計されており、AWS Cloud上にホストされる堅牢なアーキテクチャを活用しています。主要なコンポーネントは以下の通りです:

  • Frontend: TypeScript/React application.
  • Backend: Java/Spring Boot services.
  • データベース: MySQL on Amazon RDS.
  • キャッシュ: Amazon ElastiCache.

機能:

  • ユーザー機能: 商品リストの表示、詳細情報、画像の閲覧、カートと購入の管理
  • 外部統合: 支払い、在庫、配送機能はSaaS APIで提供
  • 認証: Amazon Cognitoで管理
  • ストレージと配信: Amazon S3とCloudFrontで管理

インフラストラクチャ:

  • コンテナ管理: スケーラブルなコンテナオーケストレーションのためにECSとFargateを使用
  • ネットワーキング: 複数のアベイラビリティゾーンにまたがるVPCにパブリックおよびプライベートサブネットを配置し、NATゲートウェイとインターネットゲートウェイを利用
  • CI/CD: AWS CodePipeline、CodeBuild、CodeDeployを使用して自動化し、GitHubと統合
  • 非同期通信: SQSとLambdaを使用
  • 監視: CloudWatchでパフォーマンスをトラッキング

このアーキテクチャは、高可用性、スケーラビリティ、そしてリソースの効率的な管理を確保し、ユーザーの要求に効果的に対応します。

AWS Jump Start全体を通しての感想

様々な企業のメンバーと一緒にアーキテクチャを作成したりレビューを行いました。私は通常の業務ではWebアプリケーション側の開発を行っていますが、メンバーの中にはインフラを担当している方もいて、アプリとインフラの両方の視点で議論することで新しい気づきを得ることができました。

アプリ側とインフラ側で意見が分かれたこともあったのですが合意するのは難しく、自分としては挑戦のように感じました。また今後の業務でコンテナを扱うことになるため、ECSを使った実践的な経験は非常に貴重で特に役立ちました。

全体を振り返ると、この経験は実践的な内容で非常にためになるものでした。これまでAWSのサービスについては書籍やセミナーで学んできましたが、それを実際の開発に活かすことは難しかったです。このワークショップに参加したことで、まるでドリブルやパス、シュートの練習をした後に初めてコートに立つような感覚で、次のレベルに進んだように感じました。

実践的なAWSアーキテクチャの設計経験が限られる方にとって、このワークショップは大いに学びの機会があります。一方で、自分の知識に不安がある場合はグループディスカッションに効果的に参加できるよう事前に学習をしておくことをお勧めします。

 

モビルスでは、一緒に働く仲間を募集中です!

興味のある方は、ぜひ採用情報のページをご覧ください!

CSV作成処理にStrategyパターンを適用した話

Written by Tomotaka Miyauchi

デザインパターンの図

デザインパターンとは

みなさんはデザインパターンをご存知でしょうか?

オブジェクト指向のプログラミング言語において、GoFらの経験則に基づいて提唱されたベストプラクティス集です。(その数、なんと23種類!!)

ただし、現代において、これがベストプラクティスかというと、「?」と思うパターンもそこそこあります。
無闇に使用すると可読性を損なうこともありますので、各パターンのメリット・デメリットを理解した上で利用することが重要です。

今回は、デザインパターンの中で "Strategyパターン" にリファクタリングした話を書きたいと思います。

仕様変更の内容

私が担当しているプロダクト「モビキャスト」はLINE配信を行うSaaSサービスです。
お客様のLINEアカウントにお友だち登録されているエンドユーザー様に対してLINE配信を行います。「モビキャスト」の特徴として、各エンドユーザー様にLINE上のアンケートを回答いただくことで、各ユーザーの情報に基づき、セグメントを絞った配信が可能です。また、REST APIによるLINE配信や、お友だちでないエンドユーザー様に対しても電話番号を指定した配信を行うことができます。

今回、配信結果のエンドユーザー一覧を出力するCSVに仕様変更が入りました。
こちらのCSVは、1件の配信に対して配信したエンドユーザー様の一覧を出力します。

「モビキャスト」では電話番号を指定した配信が可能ですが、
以下の表のように "配信種別(通常配信、電話番号指定)" と "出力種別" によって、CSV項目の編集パターンが異なります。

今回の仕様変更で、電話番号配信の配信結果CSVに項目を追加することになりました。

変更前の編集パターン
変更前の編集パターン

変更後の編集パターン
変更後の編集パターン

リファクタリング前の課題

リファクタリングする前のソースがこちらです。(一部変更しています)

async function getCsvContent(resultType, findQuery, isPhoneNumberPush) {
  const elemsCursor = getCursorFromResultElem(findQuery);

  if (resultType !== 'all') {
    // 出力対象が全部以外の場合
    return await getCsvContentForNotAll(elemsCursor, isPhoneNumberPush);
  } else {
    // 出力対象が全部の場合
    return await getCsvContentForAll(elemsCursor, isPhoneNumberPush);
  }
}

// 出力対象が全部以外の場合のCSV作成
async function getCsvContentForNotAll(elemsCursor, isPhoneNumberPush) {
  const csvContent = [];

  // ヘッダの追加
  csv_content.push(editHeaderPattern1());

  // コンテンツの追加(カーソルの読み込み)
  for (
    let doc = await elemsCursor.next();
    doc !== null;
    doc = await elemsCursor.next()
  ) {
    csvContent.push(editContentPattern1(doc, isPhoneNumberPush));
  }
  return csvContent.join('\n');
}

// 出力対象が全部の場合のCSV作成
async function getCsvContentForAll(elemsCursor, isPhoneNumberPush) {
  const csv_content = [];

  // ヘッダの追加
  csv_content.push(editHeaderPattern2());

  // コンテンツの追加(カーソルの読み込み)
  for (
    let doc = await elemsCursor.next();
    doc !== null;
    doc = await elemsCursor.next()
  ) {
    csv_content.push(editContentPattern2(doc, isPhoneNumberPush));
  }
  return csv_content.join('\n');
}

実装自体はとてもシンプルで可読性も良さそうな気がします。
でも、実は、この実装にはいくつかの問題点があります。

  • 単一責任の原則
    各編集パターンが独立していないため、ソースに変更があった際にどの編集パターンへの変更か、わかりづらいです。

  • 重複コード
    getCsvContentForNotAllgetCsvContentForAllはほぼ同じ処理です。この場合、編集パターンが追加されるたびに重複コードをコピーすることになり、1ファイル内のソース量が増えていきます。

  • バグの発生率
    重複コードに修正が発生すると修正箇所が多くなりバグが発生しやすくなります。

以上のことから、今後の保守性を考え、Strategyパターンでリファクタリングすることにしました。

Strategyパターンで実装

まず、クラス設計を以下のように行いました。

なお、データ取得用のDataStrategyインタフェースも作成すると、CsvStrategyと組み合わせて色々なパターンが作成できます。
今回は不要なので作りませんでした。

クラス図
クラス図

実装は以下のようになりました。

まずはストラテジのコンテキストを実行するソースです。どのストラテジーを適用するか選択し、コンテキストの処理を実行します。
(このソースはクリーンアーキテクチャでいうところのUse Casesにあたります。ビジネスロジックを組み合わせて一連の処理を実現します。)

async function getCsvContent(resultType, findQuery, isPhoneNumberPush) {
  // 出力CSVの選択
  const csvCreatorContext = new CsvCreatorContext();
  if (resultType === 'all' && isPhoneNumberPush) {
    // 「全部」タイプ and 通知メッセージの場合
    csvCreatorContext.setCsvStrategy(new ExCsvStrategyAllTypePnp());
  } else if (resultType === 'all') {
    // 「全部」タイプ and 通知メッセージ以外の場合
    csvCreatorContext.setCsvStrategy(new ExCsvStrategyAllType());
  } else {
    // 「成功」or「失敗」タイプの場合
    csvCreatorContext.setCsvStrategy(new ExCsvStrategyUserKeyOnly());
  }

  // CSV作成
  return await csvCreatorContext.createCsv(elemsCursor, isUnfollwFlagOn);
}

続いて、コンテキストの実装です。
(これ以降のクラスはクリーンアーキテクチャでいうところのEntitiesにあたります。つまり、ビジネスロジックを実装します。)

export default class CsvCreatorContext {
  #CSV_DELIMITER = ',';

  setCsvStrategy(strategy) {
    this.csvStrategy = strategy;
  }

  async createCsv(elemsCursor) {
    const csvContent = [];

    // ヘッダー出力
    const strArrayHeader = this.csvStrategy.getHeader();
    if (strArrayHeader.length > 0) {
      // 空以外の場合
      csvContent.push(strArrayHeader.join(this.#CSV_DELIMITER));
    }

    // データ行出力
    for (
      let doc = await elemsCursor.next();
      doc !== null;
      doc = await elemsCursor.next()
    ) {
      const strArrayContent = this.csvStrategy.editDocument(doc);
      if (strArrayContent.length > 0) {
        // 空以外の場合
        csvContent.push(strArrayContent.join(this.#CSV_DELIMITER));
      }
    }
    return csvContent.join('\n');
  }
}

続いて、CSV作成ストラテジーのインターフェースです。

export default class CsvCreatorCsvStrategy {
  // CSVヘッダ編集
  getHeader() {
    throw new Error("Method 'getHeader()' must be implemented.");
  }

  // CSV編集
  editDocument(doc) {
    throw new Error("Method 'editDocument()' must be implemented.");
  }
}

続いて、CSV作成ストラテジーのインターフェースの実装です。
各種CSVのフォーマットに合わせて複数のストラテジーを作成します。以下はその一例です。

import CsvCreatorCsvStrategy from './CsvCreatorCsvStrategy';

// ALLタイプのCSVストラテジ
export default class ExCsvStrategyAllType extends CsvCreatorCsvStrategy {
  // CSVヘッダ定義
  getHeader(isUnfollowFlag) {
    return [
      'haishin_shirei_id',
      'user_key',
      'result_type',
    ];
  }

  // CSV編集
  editDocument(doc, isUnfollowFlag) {
    return [
      `"${doc.haishin_shirei_id}"`,
      `"${doc.user_key}"`,
      `"${doc.result_type}"`,
    ];
  }
}

Strategyパターンにして嬉しかったこと

Strategyパターンにして1番嬉しいのは、

 「CSVの1つの編集パターンに対する修正が
    他の編集パターンに影響を与えないことが明白である点」
です。

各ストラテジーは独立しているため、修正が他のストラテジーに影響を与えないメリットがあります。また、独立していることにより、各モジュールのユニットテストコードが短くなり、テストコードの修正も容易になります。

今後、編集パターンを増やす場合も「ストラテジーの追加」と「ストラテジー選択の修正」であることが明白であるため、コーディングに迷いがなくなります。

まとめ

いかがでしたか?
デザインパターンを適用することでコードの改善が図れたでしょうか?

とあるカンファレンスで、とある企業のCTOさんが、

 「アーキテクチャ上達のためには、まずはチャレンジし、
    責任持って最後まで運用し、苦しみを糧にスキルアップするしかない」

とおっしゃっていました。

冒頭に書いたように、デザインパターンが必ずしも正解ではないです。ただし、本質的に、なぜ、そうなっているかを考えるのは有意義なことです。
可読性や保守性、テストの容易性などを考えながらいい設計にチャレンジして、より楽しいプログラミングライフを送っていきましょう!!

モビルスでは、一緒に働く仲間を募集中です!
興味のある方は、ぜひ採用情報のページをご覧ください!

モビルスでのAIエンジニアの仕事:挑戦と学び

こんにちは!AIエンジニアの森川と申します!入社から半年ほど経過したところでこの記事を書いています。

元々はメーカー研究職として働いていた私が今、AIエンジニアとして取り組んでいること、感じていることを書いてみました。自身のキャリアについて悩んでいる方や転職を考えている方にとって少しでも参考になればありがたいです。

プロフィール

大学院修士課程(生命科学系)修了後、化学メーカーで研究職として6年間勤務。その後、データ分析に興味を持ち、MLエンジニアにキャリアチェンジ。派遣エンジニアとして客先でのPoC・システム開発などを経験後、現職に至る。

入社のきっかけ

前職で経験を積む中で、自然言語処理に興味を持っていました。
また、当時は派遣エンジニアとして働いており、いずれは自社開発企業で特定のプロダクト・サービスのために働きたいと考えていたところに、ダイレクトリクルーティング経由でモビルスからカジュアル面談のオファーを受けました。
自然言語処理関連のPoCという仕事内に非常に魅力を感じた一方で、実務経験が不足していたため不安もありました。しかし、カジュアル面談で「実務経験がなくても、研究職で培った視点や自己学習で自然言語処理を学んでいることに当社は魅力を感じている。十分に仕事に活かせると思う。」という言葉をいただき、これが大きな励みとなりました。最終的に内定に至り、新たなキャリアへの期待を胸に入社を決意しました。

これまでの取り組み

MooA®(コンタクトセンターのオペレータ支援用に開発した独自AIシステム)への搭載可能性のあるAI関連技術やシステムロジックについて調査・検証を行っており、例えば以下のような取り組みを行っています。

  •    情報検索ロジック改善のための要素技術調査と性能検証
  •    音声認識モデルの調査と性能検証

また、組織関連では、チームメンバーのタスクや作成ドキュメントなどのデータをチーム全体で管理・共有するための体制整備に携わっています。

入社して感じること

ここが良い

顧客の確かなニーズに基づく検証環境
  • 目下でやることは色々とあるものの、実現したいことの方向性が明確なので、
    悩んだ時に立ち返ることができ、技術者として取り組みやすい環境です。

  • モビルスは顧客の声を直接聞ける立ち位置でビジネスを展開しており、
    技術検証や開発においても大きなアドバンテージになっていると思います。

スピード感・柔軟性
  • 意思決定の速さと柔軟性はベンチャー企業ならではだと感じます。
    検証結果を報告し、導入メリットがある場合はすぐに実用検討が始まるのを見て良い刺激を受けています。

トライアンドエラーを奨励する企業文化
  • PoCでは、「うまくいく!」と見込んで取り組んでいたことも検証してみると
    いまひとつだったということが往々にしてありますが、
    会社として、長期的な視点で理解を持ってもらえており、恵まれていると感じます。

高い自由度
  • 目標・指針は与えられますが、実現のための手法や判断に関しては  
    自身で裁量を持って取り組めています。
    手の動かし方は自身で考えたいタイプなので、私としては
    取り組みやすいと感じています。

  • 働き方の面では、週2回のリモートワークが認められており、熟考が必要なタスクはなるべくリモートで取り組むようにしています。

ここが大変

AI以外の知識のキャッチアップ
  • 業務ではAIモデルの推論精度だけでなく、処理時間やリソース負荷の最適化、
    サービングについても検証します。そのため、インフラやソフトウェア等のスキルも必要になってきますが、まだまだ不足を実感することが多く、学びの連続です。

AI 技術の進化への適応と目前タスクとのバランス
  • 日進月歩で新しい手法・基幹技術が提案されており、それ自体は面白い反面、現在の取り組みが近い将来に廃れてしまう可能性もあり、情報収集を欠かさず行うように心がけています。

  • また、新しい技術に翻弄されすぎないよう、自社での検証において真に重要なことは何か?を日々考えながら取り組んでいます。

おわりに

最も伝えたかったのは、入社して良かったということです。エンジニアとして様々な新しいことに挑戦し、仕事の幅を広げるための機会が用意されています。エンジニアとしてやってみたいことがあったり、様々な技術に触れてみたい方にはきっと合う環境だと思います。最後までお読みくださり、ありがとうございます!もし興味がありましたら、ご応募お待ちしております!

 

モビルスでは、一緒に働く仲間を募集中です!
興味のある方は、ぜひ採用情報のページをご覧ください!

Developer Summit 2024 Summerに参加してきました!

Written by Tomotaka Miyauchi

〜開催場所:JP カンファレンスタワー〜

〜看板がお出迎え〜

7/23(火)、7/24(水)にDeveloper Summit 2024 Summerが開催され、2日間とも参加してきました。上長承認を取得すれば業務時間でもカンファレンスに参加させてくれるのは本当にありがたい、感謝です!

さて、今回は17セッションを受講してきました。

特定の分野にフォーカスしたカンファレンスではないですが、チームをどう作っていくべきか、テスト自動化は行うべきか、1on1はやる意味があるのか、など多くの開発者が持ってる疑問や課題について他社からの知見を得ることができました。
また、GitHub CopilotやMS Copilotなどの生成系AIを使ったサービスがどこまで開発現場に組み込まれていき、どこまで開発者体験を向上させるのか、などの興味深いセッションも聞くことができ、楽しいカンファレンスでした。

全てのセッションを紹介すると長くなりますので、このブログでは、多くの企業で課題になっていると思われる「目標設定は好きですか?アジャイルとともに目標に向かい続ける方法(株式会社カケハシ 小田中 育生さま)」のセッションを紹介したいと思います。

目標設定が好かれない理由

私は目標設定に苦手意識がありますが、実際に会場の挙手性のアンケートでも、目標設定が好きではない or 嫌いである方が大半を占めていました。

では、このように、なぜ目標管理がなぜ嫌われているのか。いくつか理由はありますが、個人的に一番印象に残った理由は、

 

 「評価の軸は、本来、達成率ではなく実績であるべき。」

 

私自身、目標の達成率が評価に直結するため、達成可能な安牌な目標を設定しがちでした。ただ、これは個人にとっても組織にとっても悪影響です。なぜ組織にとっても悪影響なのか、以下の例を考えてみます。

 

Aさん

目標設定:1億円

実績:2,000万円

達成率:20%

 

Bさん

目標設定:100万円

実績:200万円

達成率:200%

 

達成率が評価となる場合、Bさんの方が評価されます。しかし、本来、組織として評価すべきは、実績の大きいAさんのはずです。達成率を評価に直結させてしまうと、目標設定を低く設定してしまい、結果として組織の成長を妨げる要因にもなります。

目標設定があるべき姿

では、目標設定とはどうあるべきでしょうか。

 

目標設定のメリットとして以下のものが挙げられていました。

・明確な方向性を定めゴールへ集中する

・モチベーションの醸成、パフォーマンスの向上

 

Visionに到達するための道はたくさんあります。目標設定により、たくさんある手札の中から選択肢を狭めることで、ゴールへ集中できるようになります。

 

よい目標として、以下の特徴が挙げられていました。

・目標の達成率と評価が直結していない

・納得感のある目標(目指す理由がわかる、自分ごとにできる目標)

・難しすぎず簡単すぎないいい塩梅 

 

納得感のある目標を設定するためにも、まずはチームビルディングを行う必要があります。

 

チームは価値観や経験が異なる人たちの集まりです。メンバー間で得意・不得意や人となりを知り、遠慮なく意見が出し合える関係性を構築します。また、チーム内のミッションに対する共通認識を持つために、インセプションデッキを活用して、チームの存在意義やミッションを徹底的に議論し明文化します。反対意見を出したとしても、議論をし尽くして、ここで選択した結論に対して全員でコミットすることが大切です。

 

インセプションデッキによって浮き上がってきたチームの目標に対して、メンバーの得意・不得意を考慮しながら、個人目標を設定していきます。遠慮なく意見を出し合い、議論し尽くすことによって、自分にとっても納得感のある目標を設定できます。

 

また、いい塩梅の難易度の目標を設定することで、モチベーションを醸成させ、パフォーマンスを向上させます。安牌な目標を掲げるよりも、ワクワクするような少し高めの目標を設定します。

OKRについて

GoogleやFacebookなどでも導入されている、OKR(Objectives、Key Results)でも、簡単には達成できないような少し高めの目標を設定することが推奨されています。気後れするくらい高い目標(Objectives)を3〜5個掲げ、Objectivesに対して達成度を測定する指標(Key Results)をいくつか設定します。

 

設定された目標に対してSMART観点でチェックします。なお、SMARTは各組織によって微妙に異なるため、ここでは登壇者が提示していたSMARTをご紹介します。

・Specific:何に対する改善か具体化されているか

・Measurable:進捗を定量的に示す指標であるか

・Assignable:目標にコミットするのが誰か明確になっているか

・Realistic:目標達成が現実的であるかどうか

・Time -Related:いつ目標を達成するか明らかになっているか

 

例えば、こちらのTechブログ記事を書く目標を「閲覧した方に目標設定を好きになってもらう」と設定した場合、

◯ Specific: 目標設定というスコープ

△ Measurable:はてなスターやコメント数で影響を与えたかどうかを評価

◯ Assignable:閲覧者の行動変容を促す

◯ Realistic: 私自身が目標設定を少し好きになったので現実的

× Time -Related:いつまでに達成する目標か明確でない

 

といった具合に目標をチェックします。

目標に向かって行動する

目標設定が終わると、次は目標に向かって行動します。

漠然と大きな目標に向かうのではなく、アジャイルのように目標を1週間程度の小さなサイクルに落とし込み、Key Resultsを遂行していきます。成長によりKey Resultsの再設定が必要な場合は適宜再設定します。

 

チームメンバーが目標達成に向けて行動したこと、生まれた成果についてメンバーと話し合う場を設けることも有効です。これをウィンセッションと言います。

 

ウィンセッションのスタンスとして、参加者は以下を心がけます。

 

・建設的な姿勢

 どうしてうまくいかなかった、ではなく、どうしたらうまくいくかを話し合う

 

・惜しみない賞賛

 最善を尽くしている姿勢そのものにエールを送る

 

チーム内でメンバーのお互いの得意・不得意、好き・嫌いを共有し、持ち味を生かしながら協働することが大切です。例えば、好きじゃないけど得意な仕事を、好きだけど未経験の人に引き継ぐことで、お互いがハッピーになることもあります。

まとめ

いかがでしたか?

 

少し高めの目標設定を行うことで、個人の成長はもちろん、組織への貢献にもなります。

ぜひ、皆さんもワクワクする目標設定を実施していきましょう!

参考スライド

https://speakerdeck.com/kakehashi/do-you-like-target-management

 

モビルスでは、一緒に働く仲間を募集中です!
興味のある方は、ぜひ採用情報のページをご覧ください!

ScalaMatsuri 2024 に参加しました!

こんにちは。SaaS Product Divisionの若杉です。

MOBI AGENTのバックエンドエンジニアとして1年ほど開発に従事しています。

今回は2024年6月8日〜9日にわたって開催された、Scalaのカンファレンス「ScalaMatsuri 2024」に参加してきましたので、そのうちのセッションをいくつかレポートしたいと思います。

MOBI AGENTのバックエンドはScalaで構成されています。私自身は前職から業務でScalaを扱うようになって経験年数は3年ほどと、まだまだ未熟者ではありますが、今回初めてScalaMatsuriに参加してみて本当にたくさんの良い刺激を得られたので、この場を借りて共有できればと思います。

ScalaMatsuriとは?

ScalaMatsuriとはアジア最大級のScalaのカンファレンスで、2013年開催初年度は「Scala Conference in Japan 2013」という名称で始まり、2014年開催から「ScalaMatsuri」という名称になりました。そこから大体1年に1度の頻度で開催されています。

ここ数年はコロナの影響もあり、オンラインでの開催でしたが、今回5年ぶりにオフラインでの開催となりました。

会場である東京国際交流館にはたくさんのScalaエンジニアが集まり、外国籍の方も多くいらっしゃっていて、非常にグローバルなイベントとなっていました。

ScalaMatsuriの特徴は、応募すれば誰でもセッションの登壇者として発表ができる点と、さらに事前応募ではなく当日の飛び入りセッションも設けている点です。カンファレンスは2日間にわたって開催されましたが、2日間ともいくつか飛び入りセッションが開催されていて、通常のセッションよりもっと砕けた雰囲気で、誰でも自由に発言できるような開かれたセッションとなっていました。

それでは、私が参加したセッションのうち、2つをピックアップして共有したいと思います。

ピックアップセッション①【PHPからScalaへ:私の経験】

こちらは、イタリア出身のKristian Lentinoさんによる発表で、Scala初学者やScalaをあまり知らない人にもわかりやすい内容となっていました。

余談ですが、今回のカンファレンスは英語での発表が全体の半数以上を占めていましたが、会場に通訳の方がいらっしゃり、その同時通訳をレシーバーで受信して聞くことができるという素晴らしい環境が整備されていて、私のような英語弱者でも内容をしっかり理解して聞くことができました。プログラミング用語が飛び交うセッションを通訳することは非常に困難なことだったと予想されますが、通訳の方には本当に感謝しかありません。

ということで、セッションのレポートに戻りましょう。

Kristian LentinoさんはもともとPHPを業務で扱っていましたが、転職の際にScalaを学ぶ必要があり、そこからScalaを始めた、ということでした。

セッションの前半部分はどのようにScalaを学んだか、ということで、おすすめのリソースが紹介されていました。Scalaに興味はあるけれど、何から初めて良いかわからない、という方はぜひ参考にしてみてはいかがでしょう?

https://github.com/KristianLentino99/ScalaMatsuri2024

そして、Scalaを学んで知った数々の素晴らしい点について語られていました。普段Scalaを触っていると当たり前に感じていることも、「やっぱりScalaって便利だよね!」ということを再確認できてとても良かったです。私はプログラミングを始めて最初に業務で扱ったのがScalaだったので、比較ができるほど他言語の知見がないのですが、PHP経験者からも「やっぱりScalaって良いよね」と言ってもらえたことはなんだか嬉しかったです。

紹介されていたScalaの素晴らしい点を一緒に見てみましょう。

Option型

Option型はScalaで非常によく使われる型です。PHPではこのような概念はなく、値の有無を安全に処理することができる点で優れている、と紹介されていました。nullを扱う必要がなく、とても便利で安全な型だと思います。

パターンマッチ

こちらは、Kristian Lentinoさんが一目惚れした、ということで紹介されていました。パターンマッチは可読性が高く、自動でenumの網羅性チェックもしてくれます。コードの例を見てみましょう。

val x: Int = Random.nextInt(10)

x match {

  case 0 => "zero"

  case 1 => "one"

  case 2 => "two"

  case _ => "other"

}

非常にシンプルでわかりやすく、何をやっているのか、プログラミングを学んだことがない人でもなんとなく理解できるのではないでしょうか。else ifを続ける記法よりもコード量も少なく、見た目にも美しいので私もお気に入りの記法です。

発表では漫画「ONE PIECE」のキャラクターを例に作成されたサンプルコードも用いられていて、ユニークで分かりやすい内容となっていました。

少ないコード量

Scalaの大きな魅力の一つが、コード量の少なさです。発表ではPHPでは3行で書くけるコードが、Scalaでは1行で書けることの共有がありました。

PHPのコード

$numbers = range(1, 100);

$even_numbers = array_filter($numbers, function($num) {return $num % 2 === 0;});

$sum = array_sum($even_numbers);

Scalaのコード

(1 to 100).filter(_ % 2 == 0).sum

この例が出た時に、私は思わず「おぉ〜」と声が出てしまいました。コード量を3分の1に減らせるとすれば、保守性もかなり上がるのではないかと思います。

implicit

implicitはScalaの暗黙的な値です(Scala3ではgiven)

implicitは様々な使用方法があり、そのどれもが「暗黙的に何かしてくれる」というものです。予期しない動作に繋がる危険性もあるので使いすぎるのはよくないけれど、使いこなせれば美しいコードが書ける、とのことでした。

確かに、implicitの乱用はかなり危険ではありますが、使ってみると便利でコードがスッキリするので、使い所を見極めて使用するのが良いかと思います。セッションでは円周率を暗黙的に渡すサンプルコードが紹介されていました。

私は既存の型を拡張する使い方(implicit class)が便利で好きです。

といった感じで、PHPからScalaへの壮大な旅を語ってくれました。セッションの終わりの方で「PHPの方が優れていて、懐かしいと感じる部分は?」といった質問がありましたが、「そんな部分があれば私はここに立っていない」という力強い回答がありました。

Scalaの魅力を再確認・共有できた素晴らしいセッションだったと思います。

ピックアップセッション②【Property-based testing: テストライブラリ活用方法】

次に紹介するのは、Magda Stozekさんによるテストコードに関するセッションです。プロパティベースの考え方に基づいたテストライブラリの活用についての発表でした。

もちろんScalaのライブラリに関する内容だったのですが、考え方は他の言語にも通ずるところがあるんじゃないかなぁと思ったりもしました。

事例ベースのテスト

まず、テストと聞いて思い浮かべるのは「事例ベースのテスト」ではないかと思います。

発表では、顧客の継続年数によって割引が適用される例を用いて説明されていました。

def calculateDiscount(customer: Customer, now: LocalDate): BigDecimal

case class Customer(

    name: String, 

    joinedAt: LocalDate, 

    dateOfBirth: LocalDate

)

0-1年の継続では0%、1-2年の継続では10%、2年以上の継続では20%、さらに誕生日では30%の割引が適用される場合、「事例ベースのテスト」ではテスト内容は下記のようになります。

it should "calculate 10 percent discount" in {...}

it should "calculate 20 percent discount" in {...}

it should "calculate birthday discount" in {...}

it "should calculate no didcount" in {...}

それぞれの割引率が適用される例を用いて、正しい処理かどうかを判断する。一般的な考え方ですね。

プロパティベースのテスト

では、プロパティベースではどうなるでしょう。

it "should not be lower than 0" in {...}

it "should not be over 30 percent" in {...}

it "should be proportional to membership years" in {...}

it "should not be greater than birthday discount" in {...}


割引の4つのルールに着目して、例で捉えるのではなく、その「性質」をテストするのが「プロパティベースのテスト」の考え方だそうです。

この例では、「割引率は0より小さくはならない」「割引率は30より大きくならない」「割引率は会員年数に比例する」「割引率は誕生日割を超えない」という4つのルールに着目して、それをプロパティとして定義します。

プロパティベースの考え方としては、アルゴリズムの全てを網羅する必要はないんだそうです。ある安全な範囲を指定して、処理の結果がその範囲内に収まっていれば問題ない、というのが考え方のベースとなるそう。

「割引率は30より大きくならない」の定義に対するコードはこんな感じ。

property("Discount should not be over 30 percent") {

  forAll { (customer: Customer, now: LocalDate) =>

    val discount = calculator.calculateDiscount(customer, now)

    discount should be <= BigDecimal(0.3)

  }

}

顧客とローカル日付をランダムにいくつか生み出し、その全てに対してこのテストを満たしているのかを判定してくれるそう。

確かに、ランダムにいくつもの組み合わせをテストしてくれるのはとても便利ですね。例ベースのテストでは、所詮頭の中にある、想定できうる値に対してしかテストができません。このライブラリでは想定していなかったようなトリッキーな値に対してもテスト実行が可能で、有用性があるとのことでした。

プロパティベーステストの課題

プロパティベーステストの課題についても共有されていました。

まずはそもそもの考え方が難しいので、そこで躓いてしまう可能性があること。次に、そのランダム性故に、バグが見つかり切らずに後から見つかってしまう可能性があること。

これらの課題については、まず例ベースのテストを実行すること、その後で重要なコンポーネントにのみ、プロパティベースのテストを実行すると良い、とのことでした。

確かに、事例ベースのテストと併用することで、よりその力を発揮できるように感じました。バランスが大事そうですね。

プロパティベースというテストの新しい視点に気づけた刺激になるセッションでした。

トレーニングDayについて

今回、私は6月8日〜9日のカンファレンスDayに参加しましたが、実はその前日にトレーニングDayも開催されていました。

私は参加していないので詳細は不明ですが、Scala初学者だったり未経験だったりしてもScalaMatsuriが楽しめるように、基礎的なトレーニングが行われたようです。

Scalaに興味はあるけれど、全然知識もないし。。という方はトレーニングDayから参加してみるのも良いかもしれません。

Scalaはよく難しいイメージを持たれて敬遠されがちですが、一度触れてみると「なんだ、こんなものか」となったり、その便利さに虜になると思います。あくまで個人的見解ですが。

ぜひ、たくさんの方にScalaに興味を持って欲しいです。

まとめ

いかがでしたか?ここで紹介したものは本当にほんの一部です。

ScalaMatsuri 2024のセッションの全ては動画としてアーカイブに残っています。ここで紹介したセッションも、その他のセッションも気になる方は是非覗いてみてください!

https://scalamatsuri.org/ja

私は今回、初めてScalaMatsuriに参加しましたが、どれも本当にタメになるセッションで、中には話が難しすぎてほぼ理解できないものもあったりしましたが、それも含めて本当に良い経験になったかと思います。何より、Scalaエンジニアまみれの会場がもう楽しくて楽しくて仕方なかったです。あと、お昼のお弁当がとっても美味しかったです(笑)

来年も開催されるのであれば、ぜひ参加したいです!



モビルスでは、一緒に働く仲間を募集中です!

もちろん、Scalaエンジニアも、Scalaに興味のある方も大歓迎!

興味のある方は、ぜひ採用情報のページをご覧ください!