くらしのマーケット開発ブログ

猫のいる会社、みんなのマーケットの技術ブログ

「くらしのマーケット」開発の歴史について、AWSさんに取材いただきました。

弊社が開発・運営する「くらしのマーケット」について、 開発の歴史、プロダクト開発について、AWSさんに取材いただきました。

ぜひ御覧ください。

aws.amazon.com

An adventure on getting in a Japanese company

Hi, I’m Vincent Biñas. A new hire working as a Junior Developer in Minma Inc. As my first blog post, I will talk about how I got work here.

https://user-images.githubusercontent.com/40745943/49488906-f509c180-f88b-11e8-862d-9b4012883b21.jpg

Why Japan?

I have always dreamt of working abroad, with promises of a better quality of life, good work-life-balance, and a new point of view brought on my experiencing a new culture. I have considered a number of countries near Asia. I have found Japan to be the best fit. The people, the scenery, everything was welcoming when I first visited. I have considered Singapore, where its close vicinity to the Philippines, and English language a plus. But in contrast to Japan opening its doors more to foreign workers, Singapore has stricter laws. Hong Kong was also in my list, but the high standard of living makes it nigh impossible for me to afford. Japan’s rent may also be high, but in certain places, they have great value. Weiging the pros and cons, I decided to go to Japan.

Finding out if I am up for this

Working my way into Japan, I earned enough money in the Philippines for a year. Given the uncertainties, I would like to experience living for the first time abroad for a little bit before committing. That’s when I decided that I will study Japanese in Japan for a year before finding work.

Getting into a Japanese language school has its hardships as well, but that’s for another blog post in my opinion. But long story short, I came to Tokyo, what I earned was unfortunately not enough. I found a freelance job that got me enough money to afford my stay here, and it was also a good experience that would help me later on. 3 months before my graduation, I applied and got into an interview from one of the game companies I follow.

Rollercoaster ride of emotions

I got rejected. A game company I was aiming for gave me the sad news via email. I pretty much expected the result. I breezed through the first casual interview in English, but went bananas over the second interview, which was in Japanese. Their HR, however, referred me to a recruiting agency. I was surprised when the assigned recruiter called me through my phone. After registering and going through a number of steps, the volley of referrals came in like a flood. To be completely honest, I never really had an entry there that I was interested in.

There were only car companies, medical systems, and other technical things far from what I love; games or websites! It was rather hard to choose. One had caught my eye though, Minma Inc. The company outline was quite different from the others, I should say a little more lenient, in which, feels like the specs connect to devs more. Other companies expect a lot from their applicants, not to mention how I was still in a slump from almost making it to a game company I follow. Days turn to weeks, and out of the three companies I applied to, only one proceeded with the interview. You’ve guessed it: Minma Inc.

The recruiter gave me some resources about the company, including interviews of the CEO. Given my Japanese level at that time, I had little knowledge on such unfamiliar terms, and ended up google translating most of the things written. Google translate does wonders to perfectly structured Japanese, either turning them into unintelligible pieces of English, or changing their meaning altogether. I managed to get by understanding it due to spending a year in a Japanese language school, but losing some of the nuances that would’ve shed light on what this company exactly is. Expecting a very strict atmosphere, I had mentally prepared myself, including practicing Japanese to get by. What I saw when I went to the office was the total opposite.

https://user-images.githubusercontent.com/40745943/49488672-04d4d600-f88b-11e8-998d-2e96fe22a3dc.jpg

People wearing casual clothes, no dividers, a hangout, games,

https://user-images.githubusercontent.com/40745943/49488675-08685d00-f88b-11e8-9fdf-6dae4a80b16a.jpg

https://user-images.githubusercontent.com/40745943/49488774-69903080-f88b-11e8-8af3-46879c891073.jpg

and CATS.

https://user-images.githubusercontent.com/40745943/49488678-0b634d80-f88b-11e8-8a43-f56da0b68f22.jpg

https://user-images.githubusercontent.com/40745943/49488681-0e5e3e00-f88b-11e8-90f2-8139807d21b5.jpg

I was very surprised. The first interview went by pretty well, I had little misunderstandings, and managed rather well with the questions. I passed this interview.

With my newfound confidence, I gave myself a pat on the back, and prepared for the second interview. The recruiter gave me the information about what the second interview will contain: a technical interview, and an SPI test. SPI Test? I wonder what that is? A quick google search gave me a horror story. Advanced Japanese questions that even natives have a hard time, and not to mention math questions and a personality test! I would want to study, but a leeway of 1 week was pretty unforgiving. My “newfound confidence” by this time disappeared in a jiffy. Going in for the second interview, I was a nervous wreck. I came in and found that somehow, people were surprised I’m here. I was equally confused. “How did they not expect an interviewee coming today?” I wondered. It turns out, I was a day early. I bet I turned beet red in embarrassment, they called the recruiting agency to confirm if the date was mistaken or not. Though the email confirmed that I was at fault. Wednesday, 水曜日 was written there, and it was Tuesday, 火曜日. Given how strict the Japanese custom of being punctual is, it made a nervous wreck of me even worse.

“My chances here are close to nil by now” My mind tells me. Coming in the actual date and taking the test did not really make me any more confident. The SPI was hard enough that I give myself a solid 2/10 for my performance in that test. The technical question was doable in my opinion, but what exactly what I must do is shrouded in Japanese largely unheard of by me. I managed to get an outline of the solution out, but I was not able to answer the follow-up question. Walking home with my head low, I pretty much was back on recruiting sites searching for other possible jobs. I was definitely not passing that one! God knows when I would find a company that has a good atmosphere, and cats.

With my finances and time spread thin, I had no choice but to go for another 6 months. I paid my tuition and hoped for the best for another 6 months. The recruiter that has always been in contact with me called. I expected the bad news, I couldn’t be anymore prepared to take it. But lo and behold, I somehow passed the second interview. Surprised and happy is an understatement to what I felt that time, but of course, at the back of my mind, I always know that there is still a third interview. My friends were telling me that the third interview is already a go sign. That gave me a confidence boost, but I still have caution.

The third interview was pretty much a breeze. All there was, was a talk with the CEO, and a company tour. It got me excited. It was only a matter of weeks when I got my offer letter. I finally have a job!

Conclusion

In the end I do not know if it’s by chance or not that I got here, but I am certain that it is because I carried on with a crazy dream that got me to where I am. At present, Minma Inc is a very good place to work! Free drinks and snacks, lots of leisure facilities, and awesome workmates. I have to say though, that cats here are definitely best perk. One month in and I still have ways to go when it comes to dev skills and communication, but everyone’s a champ for being great mentors, not to mention how the company gives every person abroad optional Japanese language lessons. Minma Inc is hiring by the way, so if you are interested, stop by our website at http://www.minma.jp/careers.

あとで困らないCSS設計 〜クラス名の付け方〜

はじめに

こんにちは。
みんなのマーケットのテクノロジー本部でデザイナーをしているラミレスです。
本日は「あとで困らないCSS設計」の第一回目として、「クラス名の付け方」についてお話したいと思います。

クラス名を付けるのは意外と大変

私はクラス名を付ける時に非常に悩みます。
「このクラス名をつけて、あとで誰かが困ることはないかな?」
「他で利用しているクラス名ではないかな?」

などなど。

特に子要素、孫要素など、要素が似ていると似たような名前になってしまったりして、「似たような名前が多いけど、この名前で伝わるかな?」と不安になったりしています。

そこで、今回は「できるだけ簡単」に「みんなが困らない」クラス名を付ける方法を調べてみました。

クラス名の悪い例

まずはこれまで遭遇して私が困ったクラス名(クラス名の悪い例)を紹介していきます。

(1)相対的
例えばクラス名の中に ”big” と記載があったとしましょう。

しかし、このクラス名はあまりよろしくありません。 理由は、

・大きいって誰から見て、何と比較して大きいの?
・今後もっと大きいものが出てきたらどうするの?

という問題がつきまとうためです。

例としては下記が挙げられます。

悪い例:
.big-img
.small-btn

(2)HTML要素やDOMツリーに依存している
例えば ”h2-ttl” のようなHTML要素に依存するクラス名は、「h2がh1に変化した場合に矛盾する」などの問題が生じてしまいます。
また、DOMツリーの構造に依存している “body-div-p” のような場合も同様で「pがspanに変化した場合に矛盾する」という問題が生じます。

そのため、HTML要素やDOMツリーに依存しないようなクラス名をつけましょう。

悪い例:
.body-div-p

(3)定義されていない省略形を使用

クラス名をつける時、「ボタンはbtnにしよう」とか「タイトルはttlにしよう」というようなルールや定義を組織内で決めている場合があります。
今回の悪い例は、その定義なしに勝手に省略形にして、本人以外が何を指しているかがわからないというケースです。

例えば、

.button-l
.pnNext

など。

なぜ困るのかというと、コードだけ見たときにクラス名からどこに指示を出しているのか瞬時に判断できなくなってしまうためです。
(実際の表示と照らし合わせながら、「ここのこと指しているのか」と想像しなければならない訳です)

BEMという命名規則

上記に挙げたような、「クラス名の悪い例」にならないようにするにはどうしたらいいか?
代表的な命名規則にBEMというものがあります。

まずBEMについて簡単に説明します。
BEMはBlock Element Modifierの略で、BlockとElementとModifierをルールに従ってつないだものです。

(1)Block
多くのWebページは、ヘッダー、メニュー、サーチ、フッターなどといったパーツの集まりで構成されています。BEMでは、これらのパーツをBlockと呼びます。

f:id:curama-tech:20181130161055p:plain
Blockのイメージ

例:
header
head
contents
side
sidebar
menu
search
footer

(2)Element
1つのBlockは、Block自身を構成する部品のような(Blockを構成している)ものを有しています。 例えば、検索フォームBlockなら、「入力フィールド」と「ボタン」の2つの部品で構成されています。これをElementと呼びます。

例:
ttl
body
detail
more
submit
input
btn
menu-item
list-item

(3)Modifier
同じBlockであっても、カレント状態であったり、通常の状態とエラー状態などで異なる装飾を設定する場合があります。そうした装飾に関する調整を、Modifierと呼びます。

例:
current
disabled
checked
fixed

以上がBEMの簡単な説明です。

BEMには

・__(アンダーバー2つ)--(ハイフン2つ)で接続する
・Element-Modifier間は _(アンダーバー)で接続する
・Modifierは状態の名前と値をセットにする

など、細かいルールがありますが、今回はこのBEMを応用してすぐに使える命名規則を私なりに考えてみました。

BEMの中で、Blockはどこの部分でも必ずある要素ですが、ElementとModifierは要素によって存在しない場合もあります。

そこで、今回決めた命名規則は以下の4つです。

・Blockを記載する
・ある場合はElementを記載する
・ある場合はModifierを記載する
・全てをハイフンで接続する

例えば、
「ヘッダー内にあるマイページに遷移するためのボタン」であれば

.header-mypage-btn

「コンテンツ内のソートを切り替えるタブ」であれば

.contents-sort-tab

などの名前を付けることができます。

今回挙げたのはあくまで例ですが、社内や同じ組織の人と命名規則を決めて運用することで、あとで誰かが困ることがなくなるのではないでしょうか。
(孫要素をどうするかや、Blockに使う名前を固定するなど、細かいルールも決めておくと、より簡単にクラス名を考えることにできると思います)

命名規則を決めると下記の利点を享受できるはずです。

・クラス名を付けるのに時間がかからない
・誰が見ても何を意味しているかわかる
・同じクラス名になりにくい

最後に

私たちテックチームでは「くらしのマーケット」を一緒に作る仲間を募集しています。ご興味のある方、ご応募お待ちしております!
http://www.minma.jp/careers/

話だけ聞きたい!ってことでオフィスに遊びにきていただくことも可能なのでお気軽にご連絡ください!

参考文献

https://ferret-plus.com/7808
https://app.codegrid.net/entry/bem-basic-1#toc-3
https://qiita.com/jiroor/items/17c994bd3b18c83d746d
https://en.bem.info/

OpenCVを用いたCとDjangoの特徴検出について

みなさんこんにちは、エンジニアのツヅキです。
突然ですが問題です。 みんなのマーケットのオフィスにはCDjangoという名前の猫が二匹います。
下記に2枚の画像がありますが、どちらかがCでどちらかがDjangoの写真です。
さて、どちらがCでどちらがDjangoでしょうか?

画像1 画像2

正解は、最初の画像がCで後の画像がDjangoです。
どちらがCで、どちらがDjangoかわかりましたか?(私はわかりませんでした)
そんな、どちらがどちらかわからない私のような人間はふと思います。
顔の特徴などがわかったら、2匹を判別できるのではないだろうか。。。。
さあ、ここからが本題、2匹の猫の特徴をOpneCVインテルが開発・公開したオープンソースのコンピュータビジョン向けライブラリ)[1]を用いてCDjangoの顔画像の特徴を調べていきます。

利用する画像について

今回は、4枚の画像を利用しました。

画像1 画像3 画像2 画像4jango

利用するプログラミング言語およびパッケージについて

利用する言語

  • Python3

    利用するライブラリ

  • OpenCV3

    特徴を調べる

    今回は、4枚の画像の特徴を調べるために、特徴点というものを探していきます。

特徴点とは、際立って検出できる画像上の点のことをいう。[1]

らしいです。
ということで、特徴を見ていきましょう!
特徴を検出するプログラムを以下に示します。

akaze = cv2.AKAZE_create()
face_feature = akaze.detect(img)
photo_face  = cv2.drawKeypoints(img, face_feature, None, flags=2)
cv2.imwrite(“test.jpg", photo_face)

上記のプログラム[2]によって検出された2匹の特徴を以下に示します。

c1 c2 d1 d2

上の2枚はCの特徴を検出したものです。2枚目の画像に関しては背景の画像の特徴も捉えてしまっていますが、おでこのあたりに赤の値が高めの特徴を多く捉えていることがわかります。
また、下の2枚はDjangoの特徴を検出したものです。おでこのあたりに緑の値が高めの特徴を多く捉えていることがわかります。

特徴を一致させる

先ほど特徴を調べましたが、今度は別の2匹の画像の特徴を一致させてみます。 特徴を一致させるプログラムの一部を以下にします。

akaze = cv2.AKAZE_create()
bf = cv2.BFMatcher()
kp1, des1 = akaze.detectAndCompute(img1, None)
kp2, des2 = akaze.detectAndCompute(img2, None)
matches = bf.knnMatch(des1, des2, k=2)
cat = []
for m, n in matches:
    if m.distance < 0.75 * n.distance:
        cat.append([m])
img3 = cv2.drawMatchesKnn(img1, kp1, img2, kp2, cat, None, flags=2)
cv2.imwrite(“test.jpg", img3)

上記のプログラム[3]によって検出された2匹の特徴を一致させた画像を以下に示します。

c d

上の画像が、Cの特徴を一致させた画像です。おでこのあたりに赤の特徴が一致したことを示す線と鼻のあたりに緑の特徴が一致したことを示す線があります。
また、下の画像が、Djangoの特徴を一致させた画像です。おでこから目にかけて緑の特徴が一致したことを示す線と、鼻のあたりに橙色の特徴が一致したことを示す線があります。

結果

2匹の顔画像から特徴を検出することができました。
Cは赤色が多めで、Djangoは緑色が多めということがわかりました。
これにより、人間の目で2匹を区別しなくても、特徴点から2匹を判別することができるようになりました。
この技術を応用すれば画像を自動で判別し
「写真に写っているのは人の顔なのか」
「誰が写っている写真なのか」
などがわかるようになるかもしれません。
(これは簡単な特徴を検出しただけなので、この特徴が全てではありません。
また、顔画像ではなくて、背景の中に2匹がいたらどうなるの?とか、他の猫を認識させたらどうなるの?とかはまた別のお話です。)

最後に

私は今、上記の技術を応用して、くらしのマーケットのサイトで活用できるよう奮闘中です。
私たちテックチームでは「くらしのマーケット」を一緒に作る仲間を募集しています。ご興味のある方、ご応募お待ちしております!
www.minma.jp

参考文献

[1] https://ja.wikipedia.org/wiki/OpenCV
[2] https://ja.wikipedia.org/wiki/%E3%82%B3%E3%83%BC%E3%83%8A%E3%83%BC%E6%A4%9C%E5%87%BA%E6%B3%95
[3] https://qiita.com/hitomatagi/items/caac014b7ab246faf6b1

スクラム導入後のその後

エンジニアののりすけです。以前このブログで紹介されたスクラム ( https://tech.curama.jp/entry/2018/05/18/140000 ) についてのその後のお話です。

導入した経緯などは過去の記事を見てもらえればと思いますが、私自身もどんな変化をもたらしたのか整理する意味も込めてまとめてみたいと思います。

記事時点から変わった点・継続している点

スプリント期間の変更

記事の時点ではスプリント期間を1週間としていましたが、あまりにも短いため、2週間のスプリントを試し、現在ではスプリント期間を2週間としています。

様々な書籍などでも2週間のスプリントを推奨されていますが、個人的には1週間のスプリントを以下の点から経験できてよかったと感じています。

  • スクラムという新しい動きを短い時間の中で一気に経験できた
  • スプリント期間を短くしたため毎週KPTを使った振り返りができた

KPTは継続して実施

スクラムのメリットとして上がっていたKPTですが継続して実施し、いろいろな問題点をチームで共有、解決してきました。これらの積み重ねがチームの経験として溜まってきているように感じています。

当初はKeepやProblemをどう書けばいいかなどもありましたが、現在では具体的な問題だけでなく、漠然と「なんとなくおかしい」など抽象的な意見があがってもその問題を具体化する動きや、意見の上がったことに対して何かしらの策を講じたりなどチーム自らで改善を促す動きができるようになってきました。

ツールの変更(Trello -> Zenhub)

当初ストーリーの管理をTrelloで管理していましたが、スクラムを継続しているうちに大きいユーザーストーリーの管理をどうするかという問題に突き当たってしまいました。そもそも大きすぎるストーリー自体を避けるべきなど、様々なやり方を考えては見ましたが、Epicというストーリーをまとめる機能をもつZenhubというGitHub上で動くツールに変更しています。

不満点を上げるとTrelloのサクサク動く感じから少しもっさりとした動作が個人的には気になりますが、機能面では事足りている状況です。

受入れ条件の記述が良くなった

オーナーが記述するユーザーストーリーには受け入れ条件が含まれています。我々エンジニアはこの条件を満たすように設計/実装を行うのですが、記述内容についても時間の経過に連れて変化してきました。

スクラムを始めた当初、受け入れ条件についてどう記述すべきかいろいろ分からない部分もあり単純な情報しか書かれていませんでした。スクラム運用を進めるうちに様々な失敗(受け入れ条件漏れなど)を経験し記述方法を少しずつ修正することでエンジニア視点からもわかりやすい受け入れ条件が書かれるようになりました。

ストーリーの規模も違うので一概には言えませんがスクラム運用をはじめた当初はほとんどのストーリーで数個しかなかった条件が、現在では十数個ないし30近く条件が設定されているストーリーも存在しています。

これらの修正はKPTの振り返りで「あのストーリーの受け入れはこう書くべきだった」などの意見がでたり、エンジニアからも「これを受け入れに含めてほしい」などオーナーとチームメンバー双方で受け入れ条件をちゃんと確認する習慣もできてきています。

スプリントプランニングの変化

当初の状態から大きく変化したものの1つがこのスプリントプランニングだと思っています。当初はとにかく口頭で「こんなことやる必要あるよね」などの会話を行いそこからプランニングポーカーでストーリーポイントを振っていました。

このやり方でも何度か試すうちにお互いの考えていることの理解が深まり、見積もりを行うポイントは近づいていったのですが、いざスプリントが始まるとプランニング時に想定していた事と異なるケースが発生したり、しまいにはプランニング時に何を話したか忘れるなど、どうしようもない事が発生したりしていました。

これらのことを踏まえてプランニング時に検討するべきストーリーについて設計面までチームで行った上で見積もりを行うようにしています。 設計といっても具体的には実際のストーリーを満たす実装を行うためのドメインモデルやDBモデルをプランニング時にホワイトボードに書き出すなどあくまでラフスケッチレベルの物ですが、これを行うことで見積もりの精度があがったり、プランニング時にチーム全員で一度設計を考えているため実装にスムーズに入れるなどのメリットを感じています。

また副次的な効果で設計に関するノウハウがチーム全員の学びになっているなど各メンバーのスキルアップにもつながる効果が出ていると思っています。

必要に応じたペア・モブプログラミングの実施

スクラムチーム内でのスキルのばらつきを解消するため率先してペア・モブプログラミングを行ってきました。こちらについては現時点でも行っていますが当初ほど頻繁には行っていません。特に言語化したルールのようなものはありませんが、初めて実施しようとすることだったり、実装に自身が無い場合などは今まで通り率先してペア・モブプログラミングを行っています。

頻繁に行われなくなった理由の1つは、前述の通りプランニングで大枠の設計もある程度決めているので実装時に不安に思わなくなってきているというのもあるのかもしれません。

なお、みんまでペアプロする場合はVSCode + Live Shareを組み合わせて行っています。

まとめ

まだスクラムを開始してから1年も経っておらず、改善すべき点はあるのかもしれませんが、途中段階としてアウトプットしたことで様々な変化があったことが改めてわかりました。最後に現時点状況を簡単にまとめます。

KPT

  • Keep 75件
  • Problem 101件
  • Try 39件

スクラムを開始した4月から現時点で累計101件の問題点をチームで上げ、その中ですぐに解決すべきとして改善したものが39件という結果でした。

ベロシティの推移

f:id:curama-tech:20180928095057p:plain

改めて見ると安定しているとは言い難いですが、ベロシティが上がらなかったスプリントの振り返りで原因などはつかめているので良しとしましょう。

我々みんなのマーケットテックチームでは「くらしのマーケット」を一緒に作る仲間を募集しています!興味がある方はぜひ気軽に連絡ください (コーポレートサイト https://www.minma.jp/