第7回定期勉強会「パネルディスカッション:サービスの運用保守」

第7回定期勉強会「パネルディスカッション:サービスの運用保守」

こんにちは、エキサイトのあはれんです。 4月の勉強会は、技術共有を目的にサービスの運用保守についてのパネルディスカッションを開催いたしました。 各部署1名ずつ代表エンジニアがパネラーとして参加していただき「サービスの運用保守」をテーマに話していただきました。

なお過去開催分は以下になりますので、よければ御覧ください。

tech.excite.co.jp

パネルディスカッションの内容

Q1. 利用しているコミュニケーションツールは?

Q1. 利用しているコミュニケーションツールは?

全社的にSlackを利用していることから、ほとんどの部署でSlackを利用していました。 一部の部署では、雑談部屋を作りやすいという理由でtandemの利用もありました。

Q2. テストコードを書いていますか?

Q2. テストコードを書いていますか?

すべての部署で、テストコードはあったほうが良いという意見ではあったのですが、 既存システムがテスト導入しづらい構造だったり、工数が取れない問題でなかなか難しいというのが現実のようです。

どの部署もテストを書くのを諦めてるわけではなく、ユニットテストの勉強会を開催したり、新規開発の際は最初からテスト導入する方向で取り組んでいるようです。

Q3. CI/CDでやっていることは?

Q3. CI/CDでやっていることは?

CD(Continuous Delivery)に関しては、ほとんどの部署で実施できていましたが、 CI(Continuous Integration)に関しては、テストの導入が進んでないため、まだのところが多かったです。

Q4. データは活用できていますか?

Q4. データは活用できていますか?

データの活用に関しては、エンジニア、プロデューサーともに活用できている部署、将来的に活用できるようにしていきたい部署など様々でした。

Google アナリティクスを利用している部署が多く、GA4への移行についての話が盛り上がりました。

5. 定期的にリファクタリングしていますか?

Q5. 定期的にリファクタリングしていますか?

すべての部署で、リファクタリングはしたほうが良いという意見ではあったのですが、 テストが無く動作確認が難しいこと、工数の問題で、なかなか進まないのが現実のようです。

人によってはリファクタリングと機能追加が混じってしまいレビューしづらくなってしまう問題があるので、リファクタリングをする際のルール化の必要性について話されました。

最後に

長年運用されているサービスが多く、理想通りにできていない現実がありましたが、 今回のような交流会を通して、各部署で切磋琢磨しながら理想に近づけるようにしたいと思いました。

今後とも様々な勉強会を開催していくのでよろしくおねがいします。

「Excite × iXIT TechCon」運営チームがBEST Project Awardを受賞しました!

こんにちは 👋

エキサイト株式会社の伊藤(🐦@motokiito2)です!

おおしげ(🐦@_ohshige)さん率いる我々TechCon運営チームは、社内の技術活性を目的に、約7ヶ月間の準備を経て、過去最大級の技術者向けの社内カンファレンス「Excite × iXIT TechCon」を開催しました。

「Excite × iXIT TechCon」の開催については、下記のエントリを御覧ください。

tech.excite.co.jp

そしてこの度、XTechグループ総会で、TechCon運営チームの活動が評価され「Best Project Award」を受賞いたしました! 🎉

受賞にあたって

長い期間取り組んできた「Excite × iXIT TechCon」に対して、カンファレンスに参加してくれた技術者だけでなく、XTechグループ全体からもスポットが当たったということで、とてもうれしく思っています。

また、今回の受賞は「有志で結成された組織」としての受賞というこで、とても大きな意味があることだと思っています。

「Best Project Award」は、例年では活躍する部署や事業チーム単位で選ばれており、有志で結成された組織が表彰されるのは初めてのことでした。

これを機に、今まで挑戦できなかった様々なことも、有志が集まり実現する機会が増えるのではないでしょうか。

今後について

今回の受賞によって、技術者の組織文化を醸成させるための取り組みがより進めやすくなったと思います。

今後も、社内カンファレンスの開催に限らず、文化醸成のための様々な活動に取り組んでいきたいと思っています。

カンファレンスのデザインを担当してくれた新卒デザイナーのかじもとさん奮闘記はこちら 👇👇

tech.excite.co.jp

「Excite × iXIT TechCon」の開催のウラ側を知りたい方、弊社に興味がある方はこちらも御覧ください 👇👇

www.wantedly.com

Spring BootのRedisキャッシュで、List.ofを使えるようにする方法

f:id:excite-takayuki-miura:20220418112217p:plain

こんにちは。 エキサイト株式会社の三浦です。

Spring Boot には様々な機能が用意されており、その一つに Redis へのキャッシュ機能があります。 非常に便利なのですが、少なくとも Spring Bootver.2.6.6 では、 List.of (正確には、 List.of などによって返却されるイミュータブルコレクション)等の一部の型でキャッシュが使えないという問題があります。

今回は、 List.of を使えるようにする方法について説明していきます。

Spring BootとRedisキャッシュ

Spring Boot では、spring-data-redisというライブラリを使って、任意のデータを Redis にキャッシュすることができます。 便利なのですが、少なくとも Spring Boot ver.2.6.6 の段階では、 List.of をキャッシュすると以下のようなエラーが出てしまいます。

Could not read JSON: Unexpected token (END_ARRAY), expected VALUE_STRING: need JSON String that contains type id (for subtype of java.lang.Object)\n at [Source: (byte[])\"[]\"; line: 1, column: 2]; nested exception is com.fasterxml.jackson.databind.exc.MismatchedInputException: Unexpected token (END_ARRAY), expected VALUE_STRING: need JSON String that contains type id (for subtype of java.lang.Object)\n at [Source: (byte[])\"[]\"; line: 1, column: 2]

これは、 Redis へのキャッシュ方法が原因となっています。

Redis キャッシュの流れとして、

  • キャッシュを作成する際は、Java用のデータをJSON化して Redis に保存
    • この際、Java側の型情報も一緒に保存
  • キャッシュを取得する際は、 Redis のデータをJSONからJava用のデータに変換して使用
    • この際、保存されている型情報も参照する

となっています。

List.of などの final なデータはJSON化はできるのですが、JSONからデータを戻す際に型情報の変換がうまく行かずエラーが起きてしまうようです。

List.ofをキャッシュする方法

これを解決するためには、JSONの変換周りをカスタマイズする必要があります。

Spring Boot では、 Redis キャッシュの値のシリアライザを開発者側で指定することができるのですが、それを以下のようにすれば、 List.of をキャッシュできるようになります。

    private GenericJackson2JsonRedisSerializer serializer() {
        // *1
        ObjectMapper objectMapper = new ObjectMapper()
                .activateDefaultTyping(
                        LaissezFaireSubTypeValidator.instance,
                        ObjectMapper.DefaultTyping.EVERYTHING,
                        JsonTypeInfo.As.PROPERTY
                );

        // *2
        // GenericJackson2JsonRedisSerializer.registerNullValueSerializer(objectMapper, null);

        return new GenericJackson2JsonRedisSerializer(objectMapper);
    }

少し解説していくと、

*1

基本的にはデフォルト設定と同じですが、第二引数である DefaultTyping.EVERYTHING が変わっています。 これを第二引数に入れることで、 final なものであっても型情報を保存するようになります。

*2

disable(SerializationFeature.FAIL_ON_EMPTY_BEANS) の設定に必要ですが、 DefaultTyping.EVERYTHING で使用するには GenericJackson2JsonRedisSerializer 内の一部処理を変更する必要があります。 spring-data-redisver.2.7 以降であれば処理が変更されているようなので、アップデートすれば設定しても問題ないと思われます。

最後に

List.of は、非常に便利な機能です。 使えるのであればこれを使わない手は無いので、ぜひ今回の設定をしていただき、ガンガン List.of を使っていきましょう!

なお、spring-data-redisver.2.7 以降であればデフォルトでDefaultTyping.EVERYTHINGとなっているようなので、将来的にはこの設定は不要になるかもしれません。 現在のデフォルト設定も見てみると良いでしょう。

Spring Bootで、JDBC設定にTLSプロトコルの指定が不要になった話

f:id:excite-takayuki-miura:20220411145717p:plain

こんにちは。 エキサイト株式会社の三浦です。

今回は、Spring Bootのアップデートによって、DB設定がちょっと簡単になった話をします。

Spring BootとDB設定

Spring BootでDBと接続したい場合、 application.yml ファイルに以下のように設定します。

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/sample_db
    username: sample_user
    password: sample_password
    driver-class-name: com.mysql.cj.jdbc.Driver

基本的にはこれで良いはずなのですが、実は状況次第では、これではDBと接続できないことがありました。

DB設定とTLSバージョン

この「状況」というのは、端的に言えば各種バージョンのことです。

私のときは、以下のバージョンでの開発で発生しました。

- Java 11.0.13
- Spring Boot 2.4.3

原因は、DBとの接続時のTLSバージョンです。

TLS1.2 でないと接続できないにもかかわらず、デフォルトでは TLS1.1 で接続しに行ってしまうため、接続エラーが起きていたのでした。

これを解決するためには、DBのURLに以下のパラメータをつければOKです。

spring:
  datasource:
    url: jdbc:mysql://localhost:3306/sample_db?enabledTLSProtocols=TLSv1.2
    username: sample_user
    password: sample_password
    driver-class-name: com.mysql.cj.jdbc.Driver

明示的に指定することで TLS1.2 で接続してくれるようになり、問題がなくなります。

新バージョンでは指定が不要になった

この指定ですが、実は新しいバージョンでは指定が不要になりました!

少なくとも以下のバージョンでは、指定しなくても接続できることを確認しています。

- Java 17.0.2
- Spring Boot 2.6.6

最後に

ちょっとしたことですが、ハマると少し解決までに時間がかかるところだったので、とてもありがたいです。

新しいJava・Spring Bootを最初から使っている人にはあまり関係ないかもですが、現時点でTLSバージョン指定が必要なものを使っている人や、バージョンを上げたがまだTLSバージョン指定を残している人の参考になれば幸いです。

PHPerKaigi 2022にエキサイトのエンジニアが登壇します。

2022年4月9日(土)〜4月11日(月)の日程で開催されるPHPerKaigi 2022にて、エキサイト所属のエンジニアが登壇いたします。

登壇情報については、以下をご覧ください。

登壇情報

何でもキレイにiterationする方法を考える in PHP

2022/04/10 18:30〜 Track A LT(5分)

fortee.jp

php の基本の foreach。
しっかり正しく記述できていますか?
foreach は簡単そうに見えて柔軟すぎて、結局難しかったりします。

こんな悩みはありませんか?
・foreach の中に if 文がたくさん詰まってしまう。
・Promise を foreach で回すのが難しく感じる
 ・同時実行上限
 ・終了時上限の付与
・Generator が苦手
 ・遅延処理が書けるって聞くけどよくわからない
 ・結局 foreach で終了までを全部詰め直すから読みにくくなってしまう

それらを解決する概念が下記の3つです。
・map処理
・並列処理
・遅延処理

この概念をいい感じに foreach で説明できたらいいなって思います。

PHPerKaigi 2022について

開催日:2022年4月9日(土)〜4月11日(月)

phperkaigi.jp

それでは皆さま、PHPerKaigi 2022を一緒に楽しんでいきましょう!

2回目以降のCheckstyle実行結果を見る方法

f:id:excite-takayuki-miura:20220405130322p:plain

こんにちは。 エキサイト株式会社の三浦です。

皆さんは、Checkstyleを使っていますか?

Javaのコードが指定したコード規約に即しているかをチェックしてくれるツールで、これによってコードの品質を保つことができます。

Gradleからタスクを実行したりして違反が無いかを確認できるのですが、実際に使ってみて、初見だと少しハマりそうな部分があったので、その部分について書いていこうと思います。

Checkstyleとは

Checkstyleは、Javaがコード規約に即しているかをチェックしてくれるツールです。

公式では以下のように説明されています。

Checkstyle is a development tool to help programmers write Java code that adheres to a coding standard. It automates the process of checking Java code to spare humans of this boring (but important) task. This makes it ideal for projects that want to enforce a coding standard.

人の目でわざわざチェックしていくのが面倒で、しかもプログラマチックに解決できるコード規約周りのチェックをしてくれるので、簡単にコードの品質を保つことができるようになります。

Gradleであれば、以下のように設定できます。

build.gradle

plugins {
    // ...
    id 'checkstyle'
    // ...
}

// 今回はマルチプロジェクト構成なので、 `subprojects` に細かい設定を追記
subprojects {
    apply plugin: 'checkstyle'

    checkstyle {
        configFile = rootProject.file("path/to/xxx.xml") // ここに、使用したいコード規約の設定をXML形式で作る
        toolVersion = "10.0"
        sourceSets = [project.sourceSets.main]
    }

    // ...
}

この設定をすれば checkstyleMain というGradleタスクが使えるようになるので、後はそれを実行すればチェックしてくれるようになります。

f:id:excite-takayuki-miura:20220404170517p:plain

とても簡単で非常に便利なのですが、全くコードを変更せずにもう一回実行すると、以下のような表示になってしまいます。

f:id:excite-takayuki-miura:20220404170638p:plain

先程まで出ていたはずのWarningが全く出てこなくなってしまいました。 これはどういうことなのでしょうか?

2回目以降のCheckstyle実行

実はGradleには、入出力の結果が全く同じ場合、タスクを実行せずにスキップするという機能があります。 2回目の実行時に UP-TO-DATE という文字列が出ていますが、これはスキップされたことを表しているのです。

つまり、一度 checkstyleMain を実行してしまうと、コードを変更しない限りもう一度コマンドライン上からWarningを確認することができないのです。 当然ですが、1回目しか確認できないのは大きな問題です。

ではどうすれば良いかというと、実は checkstyleMain を実行すると、その結果をHTMLファイルとして以下のパスに出力してくれます。

build/reports/checkstyle/main.html

ブラウザで開くと以下のようになっているので、これを見れば良いというわけです。

f:id:excite-takayuki-miura:20220404171246p:plain

f:id:excite-takayuki-miura:20220404171332p:plain

ページ内リンク等も適切に貼られているので、慣れてしまえば特にストレスなく確認できるでしょう。

まとめ

知ってしまえば簡単なことですが、初めてCheckstyleを触ると「さっきまで出ていたはずのWarningがなくなった…?」と混乱してしまうこともあると思います。

ぜひこの情報を参考にしてもらえれば幸いです。

ConstructorPropertiesを使ったAPIリクエストモデルでは、ParameterObjectは使えないという話

f:id:excite-takayuki-miura:20220401172710p:plain

こんにちは。 エキサイト株式会社の三浦です。

JavaのSpring Bootでは、OpenAPIのライブラリを使用することでAPIのリクエストモデルを簡単にドキュメント化することができます。

ただ、リクエスト用のモデルで ConstructorProperties を使っていると、うまいことドキュメント化ができないことがあります。

今回は、 ConstructorProperties を使ったAPIリクエストモデルでは、 ParameterObject は使えないという話をしていきます。

Spring BootとOpenAPI

Spring Bootでは、OpenAPIのライブラリを使用することで、以下のようにAPIを簡単にドキュメント化できます。

build.gradle

plugins {
    // ...
    id "org.openapi.generator" version "5.4.0"
    id "org.springdoc.openapi-gradle-plugin" version "1.3.3"
    // ...
}

実コード

package sample;

import lombok.RequiredArgsConstructor;
import lombok.Value;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.ModelAttribute;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RequiredArgsConstructor
@RestController
@RequestMapping("sample")
public class SampleController {

    @GetMapping
    public String info(@ModelAttribute SampleRequestModel sampleRequestModel) {
        return "ok";
    }
    
    @Value
    public static class SampleRequestModel {
        /**
         * サンプル文字列1
         */
        String sampleString1;

        /**
         * サンプル文字列2
         */
        String sampleString2;
    }
}

このコードによって、自動的に以下のようなドキュメントが生成されます。

f:id:excite-takayuki-miura:20220401170913p:plain

更に、以下のように @ParameterObject を付けると、より可読性が高まります。

    // ...

    @GetMapping
    public String info(@ModelAttribute @ParameterObject SampleRequestModel sampleRequestModel) {
        return "ok";
    }

    // ...

f:id:excite-takayuki-miura:20220401171131p:plain

このドキュメントはブラウザ上で見られるのですが、その画面から直接APIへのリクエストもできるため、とても便利なものとなっています。

しかし、実はリクエストモデル上で ConstructorProperties を使っていると、うまくドキュメント化されないという問題があります。

ConstructorPropertiesを使ったAPIリクエストモデルでは、ParameterObjectは使えない

リクエストモデルを、以下のようにしてみましょう。

    // ...

    @Value
    public static class SampleRequestModel {
        /**
         * サンプル文字列1
         */
        String sampleString1;

        /**
         * サンプル文字列2
         */
        String sampleString2;

        @ConstructorProperties({"test_string_1", "test_string_2"})
        public SampleRequestModel(String testString1, String testString2) {
            this.sampleString1 = testString1;
            this.sampleString2 = testString2;
        }
    }

sampleString1 はクエリパラメータ上では test_string_1 として、 sampleString2 はクエリパラメータ上では test_string_2 として受け取るので、ドキュメント上でも test_string_1test_string_2 のみが表示されていることが、こちらが意図する挙動となります。

ではまず、@ParameterObject を付けない状態でドキュメント化するとどうなるかというと、以下のようになります。

f:id:excite-takayuki-miura:20220401171629p:plain

なんとこのように、 ConstructorProperties の値とモデルのプロパティの値の両方が出てしまうのです。

更に @ParameterObject を付けると、以下のようになってしまいます。

f:id:excite-takayuki-miura:20220401171744p:plain

モデルのプロパティの値しか出ず、 ConstructorProperties の値は出てきません。

まとめ

残念ながら、現状では ConstructorProperties を使ったAPIリクエストモデルでは、 ParameterObject は使えないようです。

ConstructorProperties を使わずにリクエストモデルを作成するか、いつか対応されることを願いながら気長に待つのが良いかと思います。

2ヶ月間の就業型インターンで学んだこと

f:id:e_yamauchi_hiroki:20220330122301p:plain

はじめに

こんにちは、エキサイト株式会社でインターンをさせていただいている山内です。 今回は約2か月間、就業型インターンで何をさせてもらい、何を学んだかについてご紹介します。

自己紹介

趣味は麻雀や野球などで、家に雀卓があったりします。 あと、HipHopが好きだったりもします。

技術的なことでは、個人開発やハッカソンの経験がある程度で、実務経験などは全くありませんでした。

やったこと

では、本題です。 今回のインターンでは、メディア事業部でレシピメディアである「E・レシピ」のAPIの、PHPからJavaのSpring Bootへのリビルドをさせていただきました。

Javaはこれまで触ったことはありませんでしたが、はじめにペアプロのような形で基礎的なことや開発指針について教わることができ、スムーズに開発に参加させてもらえたと思います。

学んだこと

今回、このインターンで学んだことはとてもたくさんありました。 その中でも、「良いコードを書く」ということと、「アーキテクチャ」についてお話しします。

良いコードを書く

まず、「良いコードを書く」ということについてです。 私は今回のインターンで学ぶまでは、良いコードを書くと言っても具体的に何をすればいいのかわかっていませんでした。

そんな中、インターン中ではメンターの方に限らず、たくさんのエンジニアの方がお話してくれたり、コードレビューをしてくれたりしました。 そうしていくうちに、どういうことを考えてコードを書いているのか、何に気を付ければいいのかということが少しずつわかってきました。

アーキテクチャ

次に「アーキテクチャ」についてです。 業務レベルでサービスを運用していくにはアーキテクチャがどれだけ大切か、逆に、アーキテクチャを考えなければどうしんどくなるのか、ということについてとても勉強になりました。 例えば、きちんとアーキテクチャを考えることで、機能の新規追加や修正をする際に、他の場所への影響を最小限で抑えられるということなどです。

実例

良いコードを書くということや、アーキテクチャについて勉強になったと思う一例である、ファン登録機能に関するプルリクでの議論についてご紹介します。

まず前提として、E・レシピにはユーザが料理家をファン登録する機能があり、1ユーザーが登録できるファンの数には上限があります。 そのため、実現したい機能の流れは以下のようになります。

  • ファン登録をする際に既にファン登録している数が上限数かどうかを判定
    • 上限数以下
      • ファン登録
    • 上限数
      • エラーを返す

ここで、「ファン登録上限数を超えているかの判定をどこでするのか」ということについて議論がありました。 私ははじめ、この判定をユースケースで行っていました。 しかし、本当にユースケースに書くのが適切なのか、モデルなどで書くほうがいいのではないか、などの意見交換がありました。

話し合っていく中で、アーキテクチャのレイヤーごとの役割分担の考え方や、「良いコードを書く」というところでも話した、何を考え、何に気を付けるのか、ということに対してとても理解が深まりました。

最終的には「ファンの上限」という仕様はサービス共通のため、サービス層に書くということになりました。 このやりとりの中で、結果というよりもその過程の「考えて話し合う」というところがとても勉強になり、考えてコードを書くことの重要性を感じました。

まとめ

今回のインターンでは業務レベルでの開発を経験させていただき、たくさんのことを学ぶことができました。 しかし、考え方を理解しても実際にそれをコードに落とし込むことは難しく、まだまだ実践できていない部分が多いと感じました。 今回学んだことがゴールではなく、きちんと使えるようになるためにこれからも意識していきたいと思っています。

最後に

メンターの方々をはじめ、エンジニア、人事の方々のおかげで楽しく、たくさんのことを学べるインターンになりました。

ありがとうございました!

エキサイト株式会社で就業型インターンをさせていただきました。

こんにちは、エキサイト株式会社でインターンをさせていただいている木下です。
今回は、2〜3月の2ヶ月間、就業型インターンをさせていただいて学んだことをご紹介します。

自己紹介

趣味は、アニメ・漫画を見ること、サッカーをすることです。

高校3年で、授業でプログラミングに触れて興味を持ち、情報工学科に入学しました。
大学2年から、アプリ開発に興味を持ち、9月にエキサイト株式会社でのハッカソンインターンの「Booost」に参加しました。
そして、エキサイト株式会社に就業型で働いてみたいと思い、2〜3月の2ヶ月間、就業型インターンをさせていただきました。

技術的なことでは、アプリ開発に広く興味があり、LaravelやRuby on Rails、ReactなどでWebアプリを個人開発、SwiftでiOSアプリを個人開発やチーム開発しています。
また、ハッカソンにもよく参加しています。

インターンで行ったこと

ヘルスケア事業部に配属され、「恋ラボ」「お悩み相談室」「電話占い」の3サービスのサーバーサイド開発に携わりました。

  • 「恋ラボ」「お悩み相談室」のコラム記事周りの開発
    • コラム一覧ページの作成や、コラム記事と無料相談ページ下にコラム最新5件を表示、TOPページにコラム最新3件を表示等
  • SEO関連の画像タグの属性修正、TD(title, description)修正、カノニカルやインデックス修正

学び

インターンでは、実際にサービスを開発・運用している現場に初めて参加したこともあり、多くの学びがありました。

コードを書く上での意識

コードというのは書いた人がいなくなった後も残り続けていくものであるため、コードを書く際は、まず前提に求める挙動をすること、そして、他の人が読んだときに、分かりやすく、改修しやすいことが大事だと学びました。

また、既存のコードに手を加えるときや、コードレビューをするときなど他人のコードを読む機会がありましたが、結構大変だと感じたため、読む人の苦労を減らすということでも可読性のよいコードを書くことは重要だと学びました。
そのために、命名規則はもちろん、何を実装するためにコードを書くのか、コードのロジックを言語化して明確にしてから実装することが大切だと学びました。

チーム開発

実際にサービスを開発・運用している現場での開発方式を知り、コードレビューをもらうことで、チーム開発において、大切なこと、気をつけるべきことを学ぶことができました。

サービスを運用していくということ

当たり前かもしれませんが、サービスの運用には、様々な方々が関わっています。
エンジニア、企画、デザイナーなど様々な立場の方々が様々な視点からサービスを視て、日々より良いモノにしています。
そのため、エンジニアはコードを書くだけでなく、他の視点からの意見も聞きながら、エンジニアの視点からの意見を言っていくことで、チームとしてサービスをより良いものにしていけると学びました。

問題を解決する力

機能を実装する中で、思うように動かないことや困った時に、調べたり、人に質問したりと、解決する力が身につきました。
また、どう実装するかを考えるときに、複数のパターンを考え、メリットとデメリットを書き出すことで、よりよい実装方法を考えることが大事だと学びました。

複数のタスクを並行して処理する力

複数のタスクを並行して行わなければならない時に、優先順位づけやそれぞれにかかる時間の見積もりをしました。
見積もりは、思ってたより時間がかかることが多かったですが、複数のタスクを並行して処理していく力が身につきました。

また、当たり前ですが、きちんと連絡をすることや確認することを1つ1つやっていくことが大切だと学びました。

ミスしても、次に生かすこと

仕事をしている中で、コードレビューで指摘されたことや、ミスしてしまったことも多々ありました。
それらをただ反省するだけではなく、次同じことをしないようにどうすればいいのか考え、改善するということがとても重要だと学びました。

主体性、行動力

初めは、オンラインということや自分が質問することは相手の迷惑になるのではないかと思っていたところもあり、質問しづらかったです。
ですが、一人で詰まって時間が過ぎるよりも、人に聞くことで解決でき、相手も教えることで学びがあるということを感じ、タスクや実装についての疑問点があれば、積極的にメンターやエンジニアの方、企画の方に質問していくことができました。
その中で、指示を待っているのではなく、自分から質問するなど主体的に行動することが大切だと学びました。

技術面

実際の現場で使われている技術やコード、開発方式を知り、コードレビューをもらい、教えていただくことで、多くの知識、技術を身につけることができました。
知らない技術に対してインプットすることと、それを実装でアウトプットすることで、より多くのことを吸収できたと思います。

キャリア面

インターンでは、実際に社員の方と同じように働いていました。
そして、インターン中にエンジニアの方々とお話させていただく機会をメンターの方が作ってくださり、エンジニアになった理由、やりがい、エンジニアを続けている理由、キャリアなど、様々な質問をして、お話を聞くことができました。

その中で、今まで漠然としていたエンジニアという職業が少し明確になり、自分がどうなりたいのか、エンジニアとしてどう生きていくのかなどキャリアに関して、具体的に考えることができました。
自分の中で、将来のことで悩んでいたところがあったのですが、エンジニアの方々とお話ししていく中で、現時点での答えを見つけられたと思います。

SEOという新しい知識

SEOは、開発のなかでは、優先順位が低くなってしまいがちですが、そのサービスがユーザーに見られ、使ってもらうためにはとても重要なものです。
今回、SEOに関するタスクを行い、SEOという新しい視点からコードを見ることで、最初はカノニカルやインデックスなどおまじないだと思っていたコードも理解できるようになり、サービスを運用する上での学びとなりました。

リリースできた達成感

今回実装した「恋ラボ」「お悩み相談室」のコラム記事周りの開発では、リリースして新しいページや表示が追加されるなど、目に見える成果が大きかったため、達成感があり、とても嬉しかったです。

最後に

エキサイト株式会社での2ヶ月のインターンは、技術面でもチーム開発という面でも多くの学びがありました。
また、様々な方々とお話ししたことで、エンジニア像やエンジニアとしての生き方などキャリア面でも多くの学びが得られました。
メンターの方々をはじめエンジニアの方々、人事の方々のおかげで、とても楽しく、貴重な経験をさせていただきました。
短い期間でしたが、本当にありがとうございました。

新卒デザイナーが社内カンファレンス運営をやり切った話①

こんにちは!21新卒デザイナーのかじもとです!

2022年2月18日にエキサイトHD初・過去最大級イベントの『excite×iXIT TechCon』を開催しました〜〜〜!👏

開催についての目的や意義などは、実行委員長のおおしげさんがまとめてくださいました…!ぜひ読んでみてください😉

tech.excite.co.jp

 

このカンファレンスで私自身もLT枠に登壇したのですが、運営スタッフとしても関わらせていただきました!当日の運営はもちろんのこと、開催するまで数ヶ月かけて準備をしてきたので、その記録になれば…なブログを数回に分けて投稿します〜!

はじまり

開催経緯は上記事にあるように、社内技術組織の活性化・外部参加への練習になるようになど意味を込めて「初の社内カンファレンスをやるぞ!」とスタートされました。

が、元々わたし自身は技術組織活性化の1チームに所属していたのみで、「カンファレンス開催するにあたりデザイナーさんがいると助かる」みたいな経緯で参加しました。

初めは「ウェブサイトのデザインをお願いしたい」とかなり具体的で『依頼されて制作する』ような入り方と聞いていたので、「せっかくやるのに企画はできないのかな、モヤモヤ…」などと考えていました😂(初開催だからこそ模索しながらの仮案だったと後々知ります笑)

初めて参加したミーティングでは、なぜ開催するのかやウェブサイトである必要性など根掘り葉掘り。何度かミーティングを重ねて目的や達成したいことなどを共有し、活動の方針や運営チームが発足されて、手探りのカンファレンス運営が始まりました。

開催のために準備したこと

「作る専門として参加したくはない〜!」言いつつも、イベントを開催するにあたり準備するものは多く、結果として色々と作っていました。

ですが、「なぜ作るか理由をきちんと考えること」をメンバーと一緒にできたので、企画から参加という理想の運営像で出来たな〜と振り返ってます。(もちろん作ることは大好きなので多くても全然問題なかったです✌️)

一番初めの準備したものは、カンファレンスの顔となるキービジュアル作りでした。

概念を見える化する「キービジュアル」

過去に開催した前例もなく、カンファレンスに対するイメージは人それぞれ。それを統一するため、みんなが共通で連想できるイメージを手始めに考えました。

まずは実際のカンファレンスはどんな風にやっているのかを集めたり、各々が思うカンファレンスのイメージを集めて討論。基本的にオンラインでミーティングをしていたので、miroを使ってディスカッションしていきました。

実際のmiro
画像検索やPinterestを使ってイメージ画像を集めました

十数名で行ったワークでしたが、「カンファレンス」に対してこれだけ色々なイメージがあった訳です🤔 

ここから似ているものや近しいイメージ同士でグループ化して、カラフル・シンプル・宇宙っぽい…のようにタイトルをつけます。全部の要素を選ぶと大変なことになってしまうので、いいなと思ったものを投票してラフ案を作成するための選択肢を絞ります。

イメージを形にしてみる

投票で選ばれたのはこの3つ。選ばれた際の理由もちょっぴり記載します。

カラフル系

  • ポップで堅すぎない、元気な感じがある
  • 始まりなので賑やかに見せたい

シンプル系

  • 遠目でも分かりやすい、シンプルさがいい
  • ホールディングスのカラーと合わせやすそう

宇宙系

  • IT系と宇宙っぽさや未来感がマッチしそう、クールな印象
  • 始まりとビッグバンを掛け合わせられそう

どれもそれぞれ選んだ理由があり、それをうまく落とし込めるかデザイナーの頑張りどころ💪 それぞれのイメージから1枚絵だったりロゴタイプだったりを作ります。

色々とバリエーションを出せるように、イメージを参考にしながら自分でもイメージを追加してひたすら案を出す出す…Illustratorと睨めっこしながら、シンプル系5案・カラフル系4案・宇宙系3案の合計12案を作成しました!

f:id:KAJIJI_Design:20220322223624j:plain

作った12案たち

イメージと作成意図も記載。いろんな手法で作成できて楽しかったです😉

イメージ決定

メンバー内で投票した結果、カラフル系の2案目のこちらに決定しました!

丸・三角・四角の質素な形を組み合わせて、バラバラにサイズを変えてみたりギュッとグループにして別の形として見せることもでき、色味の印象はそのままに形の見せ方で横展開がしやすいものになってます。

この形や色をベースに、カンファレンスで必要なクリエイティブを作っていきました…!他クリエティブについては次回ブログに書きます〜!

おまけ:なぜか作ったフォント

タイトル部分のtech con beginningの文字、実はオリジナルのフォントにしていて、大文字・小文字・数字だけですがフォントを作りました。

adobe Illustratorの作業スペース

 

Image from Gyazo

大文字・小文字・数字くらいなら打てます

需要低めですが欲しい方はお声掛けください😂

次回に続く…

「WEラブ赤ちゃんプロジェクト」古都に馴染むクリエイティブ制作を考えた!

はじめまして、エキサイト株式会社・デザイナーの小野寺です。 こちらの記事でレポートを執筆した西場とともに、「WEラブ赤ちゃんプロジェクト」のデザイン・ディレクションを担当しています。

前回は「WEラブ赤ちゃんプロジェクト」の概要とともに、主に交通機関に掲載された実際の制作物と、制作時データの違いなどをメインにレポートしました。

今回は、私が「京都」という歴史ある街に掲示されるクリエイティブを制作する過程で出合った気づきなどをテーマにお伝えしたいと思います!

京都の街が素敵なのには理由がある

普段旅行には行かない人でも、修学旅行などの機会で京都には行ったことがあるよ、という方も多いのではないでしょうか。

古都の面影を今でも多く残す京都の街歩きは、タイムスリップしたような、非日常感を味わうことができると思います。

しかし、そんな素敵な体験は、大切に保存されている古い建築物などだけが生み出しているわけではない、ということを今回改めて学びました。

歴史遺産に近いほど厳格な「京都府景観条例」

1200年の年月に育まれた歴史都市である京都の街並みを守るために、京都市では2007年に「京都府景観条例」という、屋外広告や建築物にまつわる条例を制定しています。

簡単に内容を説明すると、京都市内の「建築物デザイン」「建物の高さ」「広告物」に、「配色」や「掲載場所」「高さ」などに関して規制・ガイドラインを設け、街並みの調和を保つための条例のようです。ガイドラインの厳しさは、地域別に設定され、歴史的建築物の近くになればなるほど厳格になっていきます。

多くの広告物や看板は、街並みの中で「いかに見てもらうか」「覚えてもらうか」といったポイントでレイアウトや配色が考えられていることが多いです。制限を設けなければ、そうしたバラバラに目を引く色の無法地帯と化してしまい、美しい景観が損なわれてしまう、というのは納得です。

▼京の景観ガイドライン - 広告物編 https://www.city.kyoto.lg.jp/tokei/cmsfiles/contents/0000056/56450/guideline_all.pdf

(このガイドラインを作り上げた人々がまずすごい)

景観の守り方:派手な色はNG!マクドナルドやセブンイレブンも例外はない!

どういうこと?と思われた方はぜひwebで画像検索してみてください。 見慣れた大手企業さん達がガイドラインに合わせてコーポレートカラーを調整して京都の街に馴染んでおられます。

🔍京都 景観色

どの色ならOKなのか、という基準はガイドラインに「マンセル値」で表記されています。とても簡単にいうと、明度と彩度の高い「派手な」色はアウト、少し明るめの規制対象色は、使う面積を少なくしてインパクトを弱めてね、ということが示されています。

ガイドラインの一例

京の景観ガイドライン- 広告物編より

「WEラブ赤ちゃんプロジェクト」のキーカラーを調整する

さて、今回のプロジェクトの制作物の中には光栄なことに、ガイドライン上規制がかかる、風情ある地域に掲示されるクリエイティブもいくつか含まれており、ご担当者さまから別途キーカラーの調整が必要、とのご連絡をいただいておりました。

デジタルを主戦場とする我々にとっては、多く建築業界などでのスタンダードとなっている「マンセル値」自体が馴染みが薄く、四苦八苦しつつもブランドカラーのイメージを崩さずにガイドラインを守れる配色を以下のプロセスで選定し直しました。

▼プロセス

先方のご担当者さまより、今回は「マンセル値の彩度6以下」という指定をいただき、最終的にはDICのカラーコードでセーフな色かチェックをしてくださるということだったので、入稿時に指定しているCMYKのコードをDICカラーに変換して弊社でもツールでマンセル値を確認しながら、また色見本帳とにらめっこをしながら色を決める、という流れで最終的な色を決めました。

下の画像の通り、マンセル値を彩度6以下にすることで、少し黄色みがかったマイルドな色になりましたね!

とはいえ、素材によってどんな色が出るのか、刷るまでわからないのが印刷物・・!実際のクリエイティブはどのようになったのでしょう・・!

実際のラッピングバスはこうなりました!

▼入稿データ

▼実際のクリエイティブ

太陽光や写真の具合もありますが、イメージしていたよりも少し鮮やかに、心配するほどには渋い仕上がりにはならなかったようです😀 ほっと一安心する瞬間です。

その他にも前回の地下鉄に引き続き、商店街のフラッグや、バスロータリーの柱などにも「WEラブ赤ちゃんプロジェクト」の赤ちゃんが続々出現中です! 今回制作したグッズ・広告を通じて、少しでも多くの人に「みんなが温かく見守る子育て」について再認識してもらえたら嬉しいです。

最後に

今回の京都府の官民が一体になった「京都府子育て環境日本一推進会議」様とのコラボは、歴史都市ならではの「景観色」についての理解を深め、また、初めて現地視察を行ったことで、机上では体感できなかった改善点なども見つかる良い機会となりました。

プロジェクトのデザインガイドラインをブラッシュアップしつつ、今後ともコラボレーションする団体さまと調和するクリエイティブ制作を行なっていきたいと考えています。

🎉Canva勉強会を開催しました🎉

こんにちは。21卒デザイナーの山崎です。 先日Canpa Proアカウントが事業部で解禁されたので「第1回Canva勉強会」を開催しました。

参加人数は第1回と第2回で合計26名になりました!

何でやったの?

現在エキサイトではAdobeアカウントを利用しているビジネス職や企画職の方が多いという課題があり、Adobeでやっている仕事をCanvaで代用してコストカットを行いたいという目的でCanva布教説明会を開催しました。

Canva説明会では、便利な機能やデータの命名規則など基本的なことを説明しました。

ただ説明しても分からないので、実際にバナーを製作しながらCanvaの機能を説明してデモンストレーションを行いました。

このバナーを0から作るデモンストレーションを行いました!(このウェビナーは架空のイベントです。)

終わりに

デモンストレーションを行ったことでCanvaの魅力をより伝えることができてよかったです!

この説明会をきっかけにCanvaに切り替えてくれる社員が増えればいいなと思いました!

最後に、エキサイトではデザイナー、フロントエンジニア、バックエンドエンジニア、アプリエンジニアを絶賛募集しております!

興味があれば連絡いただければと思います🙇‍♀️

それではまた!

www.wantedly.com

第6回定期勉強会「CTOと討論会」

f:id:ixit_someya:20220324162159p:plain
第6回定期勉強会「CTOと討論会」
canva(https://www.canva.com/)より作成

こんにちは、iXITの染谷です。
3月の勉強会は「CTOと討論会」でした。
exciteHD CTOの藤田さんにエンジニアとしての在り方を語っていただきつつ、エンジニアの疑問に答えていただく貴重な機会でした!

CTOのお話

1. 芯となる思考・ビジョンを持つ

2. 組織の中での自分のアイデンティティを考える

3. 多くのことに好奇心を持つようにする

4. 強いメンタル

1. 芯となる思考・ビジョンを持つ

exciteHDであればデジタルネイティブ発想で心躍る未来を作る」など。
芯となる考えを持っておくことで、時代が変わっていっても、その考えを元に新しいものを生み出すことができる。

2. 組織の中での自分のアイデンティティを考える

エンジニアは先人たちが築き上げた様々な分野の知識を横断して用い、課題を解決する存在である。 そのため、コンピュータなどの知識のみならず、統計、経済、社会学など、あらゆる分野の知識が必要になる。
そのような知識を持っておくことで、応用が効くようになり、より柔軟で適切な課題解決方法を生み出すことができると考える。
エンジニアには既存のツールを使用するだけでなく、様々な学問の基礎を理解するように努めてほしいと考えている。

様々な分野への知識を持つことで、エンジニアとしてのアイデンティティが確立されるはず。

3. 多くのことに好奇心を持つようにする

様々分野を学ぶためには好奇心を持つことが肝要。 また、好奇心を抱くためには心身のリソースを常に確保しておくことも重要である。
好奇心の種を探すには、本やRSSリーダーSNSなどがおすすめ。
インプットと同時にアウトプットを行うことも重要。特に対象がソフトウェアなどPC上で完結するものなら実際に触るとより理解を深めるとこができる。

4. 強いメンタル

強いエンジニアには強いメンタル。
・誰よりも先に率先して行動を起こす
・環境に依存しない
・つらくなったら「1. 芯となる思考・ビジョンを持つ」の自分の目的に立ち返る

エンジニアとのQA

Q. 課題を紐解くときに、先人の知識を学ぶとのことでしたが、どのようにして知識集めするといいでしょうか?
(心理学、統計学をいきなり学ぶのはムズカシイので..)
A. 自分にとって不足している部分・知識を埋めるように情報収集する 自分の知らないことについて知る ネットなどで論文などを読む、本を読んで体型的に学ぶ、コードを書く(実践する)


Q. 藤田さんのお給料はどのくらい?
A. みんなが思っているほどはもらっていない笑
仕事でやりたいことができることを重要視しているので、ある程度の生活水準が満たせるお給料がもらえればいいと思っている。


Q. 今気になってる分野は何?
A. web3関連と量子コンピュータが気になっている。
web3はスマートコントラクト、NFT、暗号通貨などが特に面白いと思っている。
量子コンピュータは社会に与えるインパクトが大きく、プログラミングの形も大きく変わる可能性があり、面白い。

過去回

tech.excite.co.jp

tech.excite.co.jp

tech.excite.co.jp

tech.excite.co.jp

tech.excite.co.jp

Javaで形態素解析!SudachiをSpring bootで利用してみよう

こんにちは。いつものtaanatsuです。
今日はSpring bootにSudachiを入れてさっぱりさせていきたいと思います。
それではやっていきましょうか。

Spring bootの準備

Spring bootのプロジェクトはSpring Initializrを使うと楽に作れます。
ひとまず必要最小限で作っていきましょう。
Javaのバージョンはお使いの環境に合わせて選択してください!

f:id:taanatsu:20220317163617p:plain
Spring Initializr

GENERATEボタンを押下するとZIPファイルがダウンロードされるので
展開してIDEで開きます。
今回はIntelliJ IDEAで作業していきます。

IntelliJ IDEAだとGradleのくるくるボタンを押下すると、自動で必要なライブラリを集めてきてくれます。
便利ですね!

f:id:taanatsu:20220317163730p:plain
Gradle

とりあえずControllerを作ってみる

/src/main/java/com/example/demo/配下に、controllerディレクトリを作り、SudachiController.javaを入れます。
▼▼▼▼ f:id:taanatsu:20220317164809p:plain

SudachiController.javaの中身は以下のようにします。

package com.example.demo.controller;

import lombok.RequiredArgsConstructor;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

@RestController
@RequiredArgsConstructor
@RequestMapping("/")
public class SudachiController {
    @GetMapping("/")
    public String index() {
        return "hello";
    }
}

ここまでできたら右上の三角マークを押します。

f:id:taanatsu:20220317165309p:plain
実行ボタン

するとコンパイルされるので、待ちます。
コンパイルが終わると http://localhost:8080 にアクセスするとページが表示されると思います。

Sudachiを導入する

今回のSpring bootはライブラリ管理ツールに「Gradle」を使っているので、
以下の行をdependenciesの中に追加します。

implementation group: 'com.worksap.nlp', name: 'sudachi', version: '0.5.3'

f:id:taanatsu:20220317170209p:plain

その後、Gradleのくるくるボタンを押します。

f:id:taanatsu:20220317163730p:plain
Gradle

コレで準備完了です。

Sudachiの必要なもの(辞書など)を用意する

Sudachiを使うには、設定ファイルが必要です。
必要なのは「sudachi.json」と「char.def」です。
これらはSudachiのGitHubリポジトリから取得できます。

上記2つのファイルを
/src/main/resources/配下にsudachiディレクトを作成し、その中に入れます。

次に、形態素解析に必要な辞書「system_core.dic」を準備します。
この中の、どれでもいいですがひとまずsudachi-dictionary-latest-core.zipをダウンロードしてきます。
コレも解凍して、「system_core.dic」名前にして/src/main/resources/sudachi/配下に保存します。

f:id:taanatsu:20220317172501p:plain
Sudachiに必要なファイルの準備

コレで準備完了です。(2回目)

Sudachiで形態素解析をする

SudachiController.javaの中身を以下のように変えていきます。

package com.example.demo.controller;

import com.worksap.nlp.sudachi.Dictionary;
import com.worksap.nlp.sudachi.DictionaryFactory;
import com.worksap.nlp.sudachi.Morpheme;
import com.worksap.nlp.sudachi.Tokenizer;
import lombok.RequiredArgsConstructor;
import org.springframework.core.io.ClassPathResource;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.List;

@RestController
@RequiredArgsConstructor
@RequestMapping("/")
public class SudachiController {
    @GetMapping("/")
    public String index() throws IOException {
        // 形態素解析したい文章
        final String text = "こんにちは、世界";

        // 設定ファイルの読み込み
        final Path sudachiSettingJsonPath = new ClassPathResource("sudachi/sudachi.json").getFile().toPath();
        final String sudachiSettingJson = Files.readString(sudachiSettingJsonPath);

        // 辞書ファイルの読み込み
        final String sudachiDictionaryDirectory = new ClassPathResource("sudachi/").getFile().toPath().toAbsolutePath().toString();
        final Dictionary sudachiDictionary = new DictionaryFactory().create(sudachiDictionaryDirectory, sudachiSettingJson);

        // 形態素解析を行うインスタンスの作成
        Tokenizer tokenizer = sudachiDictionary.create();

        // 形態素解析の実行
        final List<Morpheme> tokenList = tokenizer.tokenize(Tokenizer.SplitMode.C, text);

        // 形態素解析の結果をとりあえず変形
        final String result = tokenList.stream()
                .map(morpheme -> morpheme.surface() + "は" + "「" + morpheme.readingForm() + "」と読み、品詞は「" + morpheme.partOfSpeech().get(0) + "」で、標準形は「" + morpheme.normalizedForm() + "」です。<br>")
                .collect(Collectors.joining());

        return result;
    }
}

そしてビルドボタンを押下し、コンパイル終了後に
http://localhost:8080 にアクセスしてみましょう!

f:id:taanatsu:20220317172929p:plain

形態素解析、されましたね!!

終わりに

自然言語処理系はPythonがやはり強いですが、
Javaでやると型がしっかりしていてその分保守性が上がりそうですね!

みなさんもぜひ、Javaでも自然言語処理をしてみてください。

……あ、今回はサンプルなのでControllerに全部処理を書いていますが、ServiceやRepositoryを使って分けて処理を書くほうがいいですね!
プロジェクトで使う際はご注意を!

それでは、また次回!

GitHubのIssueでは、Milestoneが役に立つという話

f:id:excite-takayuki-miura:20220323161337p:plain

こんにちは。 エキサイト株式会社の三浦です。

皆さんは、GitHubでIssueを使っているでしょうか? 今回は、Issueを使う場合、併せてMilestoneを使うのがオススメ、という話をします。

GitHubのIssue

GitHubには、Issueという機能があります。

コードを書いているときや使用しているときに、なにか問題や改善点を発見することもあると思いますが、そういった場合にIssueに書き込むことで、TODOリストとして保存しておくことや、他の人に問題点を共有できたりします。

非常に便利な機能なのですが、便利であるがために問題が発生することもあります。

f:id:excite-takayuki-miura:20220323145442p:plain

(当たり前ですが)Issueをたくさん使っていると、このように大量のIssueができてしまいます。

こうなると大変で、どのIssueを優先的に、いつまでに対応するべきかがとてもわかりづらくなってしまうのです。

そこで有用になってくるのが、「Milestone」という機能になります。

Milestone

Milestoneを作成し、各Issueに設定することで、文字通りそれぞれのIssueのマイルストーンを設定することができます。

f:id:excite-takayuki-miura:20220323162052p:plain

f:id:excite-takayuki-miura:20220323145703p:plain

f:id:excite-takayuki-miura:20220323161150p:plain

Milestoneのタイトルや説明に詳細を記し、オプションで日付を設定することで、そのIssueをどのタイミングまでにやるべきかを明確に示すことができるようになるのです。

またIssueの画面では、Milestoneでフィルタリングすることもできるので、特定のMilestoneのIssue一覧も簡単に出すことができ、管理が非常に容易になります。

f:id:excite-takayuki-miura:20220323161913p:plain

最後に

GitHubには様々な機能があります。

そのために使っていない機能がある場合も多いと思いますが、よく見てみると便利な機能がたくさんあったりするので、積極的に使っていきましょう!