登録したクレジットカード情報を使って商品を購入する実装

 登録したクレジットカード情報で商品を購入する実装を紹介します。商品を購入できる機能自体は実装済で話を進めていきます。これから伝えるのは、新しくクレジットカード登録画面を設けて、登録している場合はクレジットカード情報を毎度入力しなくても購入ができるようになる実装です。

 この実装を行うことで、クレジットカード情報を登録してもしなくても商品の購入が可能となります。

 

 僕はこの実装にかなり苦戦しました(笑)。Formオブジェクトを用いており、クレジットカード情報と同時に住所や電話番号なども送信できるようにしていることも、苦戦の原因です。

 プログラミング初心者であるため、可読性が高い実装ではないことはご容赦ください。またブログの仕様上、インデントが整っていない場合もあります。

 

 では説明していきたいと思います。いろいろと苦戦したのですが、結果的に行ったことはシンプルでした。以下の5点の流れで説明していきます。

 

1. name属性を区別して実装する

2. クレジットカード登録後はjavascriptを読み込ませない

3. コントローラー内で条件分岐をする

4. バリデーションがかかるような記述を加える

5. 可読性を上げる

 

 

 

1. name属性を区別して実装する

 新しくカード登録画面を作った際に最初に起きた問題が、name属性にありました。僕が行いたかった実装は、クレジットカードを登録してもしなくても商品を購入できるようにすることでした。しかし新しくカード登録画面を作った場合、カード登録画面と、購入画面では、カード情報を入力するフォームのname属性が異なります。

 カード登録画面では、カードナンバーを入力するフォームのname属性が"number"だったのに対し、購入画面では"order_address[number]"となっていたのです。購入画面では、住所や電話番号なども同時に送信できるように、Formオブジェクトを用いているからです。

 そこで、2つのことを試してみました。"order_address[number]"といったname属性をカード登録画面のviewに追記してみることと、もともと作っていたjavascript内で条件分岐をさせることです。条件分岐で行いたかったのは、カード登録画面では"number"、購入画面では"order_address[number]"を取得するといった記述です。しかしどちらもあまりうまくいきませんでした。

 そしてそれ以外の方法として、もともと作っていたjavascriptファイルとは別で、カード登録画面用のjavascriptファイルを新しく作ってみたところ、登録はできるようになりました。

 

もともと作っていたcard.js

const pay = () => {
 
Payjp.setPublicKey(process.env.PAYJP_PUBLIC_KEY);
const form = document.getElementById("charge-form");
form.addEventListener("submit", (e) => {
e.preventDefault();

const formResult = document.getElementById("charge-form");
const formData = new FormData(formResult);

const card = {
number: formData.get("order_address[number]"),
cvc: formData.get("order_address[cvc]"),
exp_month: formData.get("order_address[exp_month]"),
exp_year: `20${formData.get("order_address[exp_year]")}`,
};

Payjp.createToken(card, (status, response) => {

if (status == 200) {
const token = response.id;
const renderDom = document.getElementById("charge-form");
const tokenObj = `<input value=${token} name='token' type="hidden"> `;
renderDom.insertAdjacentHTML("beforeend", tokenObj);
}
 
document.getElementById("card-number").removeAttribute("name");
document.getElementById("card-cvc").removeAttribute("name");
document.getElementById("card-exp-month").removeAttribute("name");
document.getElementById("card-exp-year").removeAttribute("name");

document.getElementById("charge-form").submit();
});

});
};

window.addEventListener("load", pay);

 

新たに作成したcard_save.js

const save = () => {
 
Payjp.setPublicKey(process.env.PAYJP_PUBLIC_KEY);
const form = document.getElementById("charge");
form.addEventListener("submit", (e) => {
e.preventDefault();
 
const formResult = document.getElementById("charge");
const formData = new FormData(formResult);


const card = {
number: formData.get("number"),
cvc: formData.get("cvc"),
exp_month: formData.get("exp_month"),
exp_year: `20${formData.get("exp_year")}`,
};

Payjp.createToken(card, (status, response) => {

if (status == 200) {
const token = response.id;
const renderDom = document.getElementById("charge");
const tokenObj = `<input value=${token} name='card_token' type="hidden"> `;
renderDom.insertAdjacentHTML("beforeend", tokenObj);
}
 
document.getElementById("card-number").removeAttribute("name");
document.getElementById("card-cvc").removeAttribute("name");
document.getElementById("card-exp-month").removeAttribute("name");
document.getElementById("card-exp-year").removeAttribute("name");

document.getElementById("charge").submit();
});

});
};

window.addEventListener("load", save);

 

 新たにjavascriptファイルを作成したときに、読み込みの記述を忘れてしまうという初歩的なミスもしてしまったので気をつけてください。console.logやdebuggerを地道に試していけばどこから読み取れていないかを確認できます。

app/javascript/packs/application.js

 
require("../card_save")
 

 

 また、もともと実装していた購入処理はorders_controllerに記述していますが、新しく追加したカード登録の処理では、cards_controllerを用いています。購入画面からクレジットカード登録のリンクに飛んで、登録ボタンを押したら購入画面に戻るような設定にしているため、このような記述となっています。

app/controllers/cards_controller.rb

class CardsController < ApplicationController
def new
session[:previous_url] = request.referer
end

def create
Payjp.api_key = ENV['PAYJP_SECRET_KEY']
customer = Payjp::Customer.create(
description: 'test',
card: params[:card_token]
)

card = Card.new(
card_token: params[:card_token],
customer_token: customer.id,
user_id: current_user.id
)

if card.save
redirect_to session[:previous_url]
else
render :new
end
end

def session_clear
session[:previous_url].clear
end
end

 

2. クレジットカード登録後はjavascriptを読み込ませない

 これでクレジットカード登録が完了しました。登録が完了すると登録したカード情報が購入画面に表示されるようになっています。

app/views/orders/index.html.erb

<% if @card.present? %>
<div class='credit-card-form'>
<h1 class='info-input-haedline'>
クレジットカード情報入力
</h1>
<div class="form-group">
<div class='form-text-wrap'>
<label class="form-text">カード情報</label>
<span class="indispensable">必須</span>
</div>
<%= "**** **** **** " + @card[:last4] %>
<div class='available-card'>
<%= image_tag 'card-visa.gif', class: 'card-logo'%>
<%= image_tag 'card-mastercard.gif', class: 'card-logo'%>
<%= image_tag 'card-jcb.gif', class: 'card-logo'%>
<%= image_tag 'card-amex.gif', class: 'card-logo'%>
</div>
</div>
<div class="form-group">
<div class='form-text-wrap'>
<label class="form-text">有効期限</label>
<span class="indispensable">必須</span>
</div>
<div class='input-expiration-date-wrap'>
<%= @card[:exp_month] %>
<p></p>
<%= @card[:exp_year] %>
<p></p>
</div>
</div>
</div>
<% else %>

 

 下記の記述が使えるのは、orders_controllerのindexでカード情報の定義をしているからです。

 
<% if @card.present? %>
 

 

 それではこの状態で購入ボタンを押してみます。すると、そもそも購入ボタンが押せない問題が発生しました。どうやらjavascriptに問題がありそうです。card.jsとcard_save.jsに記述している「e.prevent.Default()」が動いていることが原因だと考えられます。これを動かないようにすれば解決できそうです。

 購入の処理自体はコントローラーで行うため、カードの登録が完了している場合は、card.jsとcard_save.jsの両方を読み込ませないようにする必要があります。

 そこでカードを登録している場合のみ、"save_card"というidを付け加えました。

app/views/orders/index.html.erb

<% if @card.present? %>
<div class='credit-card-form', id="save_card">
<h1 class='info-input-haedline'>
クレジットカード情報入力
</h1>

 そしてcard.jsとcard_save.jsの両方に、"save_card"というidを取得したときは、それ以降の記述を読み込ませないようにしました。

app/javascript/card.js

const pay = () => {
const saveCard = document.getElementById("save_card")
if (document.getElementById("save_card")) {
return saveCard;
};

app/javascript/card_save.js

const save = () => {
const saveCard = document.getElementById("save_card")
if (document.getElementById("save_card")) {
return saveCard;
};

 これで購入ボタンは押せるようになります。

 

3. コントローラー内で条件分岐をする

 しかし購入ボタンが押せるようになったところで、購入ができるようになったわけではありません。カードを登録している場合と登録していない場合で購入の処理を分ける必要があります。登録している場合もしていない場合も同じ購入画面で処理を行うので、orders_controllerを用います。

 createアクションでprivateメソッド内のpay_itemを呼び出すようにしています。その時にpay_itemの処理をカード登録している場合としていない場合で条件分岐させます。

app/controllers/orders_controller.rbのprivateメソッド内

def pay_item
if @card.present?
Payjp.api_key = ENV['PAYJP_SECRET_KEY']
customer_token = current_user.card.customer_token
Payjp::Charge.create(
amount: @item.price,
customer: customer_token,
currency: 'jpy'
)
else
Payjp.api_key = ENV['PAYJP_SECRET_KEY']
Payjp::Charge.create(
amount: @item.price,
card: order_params[:token],
currency: 'jpy'
)
end

 

 またindexアクションでもcreateアクションでもカード情報の定義をする必要があったため、privateメソッド内にsave_cardとしてカード情報の定義をまとめました。indexアクションでsave_cardを呼び出さなければ、登録したカード情報が購入画面に表示されなくなります。このsave_cardをindexアクションとcreateアクションの両方で呼び出すようにしました。

app/controllers/orders_controller.rbのprivateメソッド内

def save_card
Payjp.api_key = ENV['PAYJP_SECRET_KEY']
card = Card.find_by(user_id: current_user.id)

if card.present?
customer = Payjp::Customer.retrieve(card.customer_token)
@card = customer.cards.first
end
end

 

 これで後はcreateアクションでsave_cardとpay_itemを呼び出すような記述をすれば、登録したカード情報で購入すること自体は完了します。createアクション内の記述は後述します。

 

4. バリデーションがかかるような記述を加える。

 ところがこれでもまだ問題があったのです。今回の実装ではorder_address.rbというFormオブジェクトを用いていたことに問題の原因があります。下記のコードはページに収めるためにやや変更したものです。

app/models/order_address.rb

class OrderAddress
include ActiveModel::Model
attr_accessor :item_id, :user_id, :postal_code, :prefecture_id, :city, :address,
:building, :phone_number, :token

with_options presence: true do
validates :item_id
validates :user_id
validates :postal_code, format: { with: /\A[0-9]{3}-[0-9]{4}\z/}
validates :city
validates :address
validates :phone_number, numericality: { only_integer: true }
validates :token
end

validates :prefecture_id, numericality: { other_than: 1, message: "can't be blank" }
validates :phone_number, length: { minimum: 10, maximum: 11 }

def save
order = Order.create(item_id: item_id, user_id: user_id)

Address.create(postal_code: postal_code, prefecture_id: prefecture_id, city: city,
address: address, building: building,
phone_number: phone_number, order_id: order.id, user_id: user_id, item_id: item_id)
end
end

 Formオブジェクトを用いた場合は、createアクション内でバリデーションの記述をしなければバリデーションがかかりません。

 
if @order_address.valid?
 

 save_cardとpay_itemを呼び出せば登録したカード情報で購入すること自体は可能です。しかしバリデーションの記述をしていない場合は、登録に失敗した時にエラーが起きます。

 とはいえ、

if @order_address.valid ?という記述をして購入ボタンを押すと、token can't be blankというバリデーションがかかるのです。

 カード登録をしていない場合は、購入画面でカード情報を入力するため、"order_address[token]"というように、tokenがorder_addressの中に格納されるため、購入することができます。しかしカード登録画面ですでにカード情報を登録して購入画面に戻った場合は、購入画面でカード情報を入力しません。そのためorder_addressの中にtokenだけが格納されていない状態になってしまうのです。

 

 そこで2つのことを試してみました。まずカードを登録しているときだけ、tokenのバリデーションをかけないように下記の記述をしてみました。

 
if @order_address.where.not(token: params[:token]).valid?
 

 ところがこれではwhereが定義されていないというエラーが起きます。そして今度はorder_addressモデル内でifオプションを用いて、カード登録しているときだけtokenのバリデーションをかけないようにしようとしましたがうまくいきませんでした。

 あと1歩なのにどうしようと悩んだ結果、「付け加えてみよう」と考え、カード登録をしているときだけ、下記の記述を加えました。

 
@order_address.token = current_user.card.customer_token
 

 結果的にこれでうまくいきました。createアクション内の記述は以下のようになりました。カードを登録している場合はtokenの記述を書き加えた上でバリデーションをかけるようにしました。インデントが整っていないので見づらいと思いますが、許してください。

def create
@order_address = OrderAddress.new(order_params)
if save_card
@order_address.token = current_user.card.customer_token
if @order_address.valid?
pay_item
@order_address.save
redirect_to root_path
else
render 'orders/index'
end
elsif @order_address.valid?
pay_item
@order_address.save
redirect_to root_path
else
render 'orders/index'
end
end

 

 

5. 可読性を上げる

 追記です。さすがに同じ記述を何度も繰り返し書いていて読みづらいので書き直してみました。インデントが整っていなくて読みづらいのは申し訳ありません。ブログの仕様上です。

app/controllers/orders_controller.rbbの全体

class OrdersController < ApplicationController
before_action :authenticate_user!
before_action :set_order
before_action :move_to_index

def index
@order = Order.new
@order_address = OrderAddress.new
Payjp.api_key = ENV['PAYJP_SECRET_KEY']
card = Card.find_by(user_id: current_user.id)

if card.present?
customer = Payjp::Customer.retrieve(card.customer_token)
@card = customer.cards.first
end
end

def create
@order_address = OrderAddress.new(order_params)
Payjp.api_key = ENV['PAYJP_SECRET_KEY']
card = Card.find_by(user_id: current_user.id)
if card.present?
customer = Payjp::Customer.retrieve(card.customer_token)
@card = customer.cards.first
@order_address.token = current_user.card.customer_token
end

if @order_address.valid?
pay_item
@order_address.save
redirect_to root_path
else
render 'orders/index'
end
end

private

def order_params
params.require(:order_address).permit(:postal_code, :prefecture_id, :city, :address,
:building, :phone_number, :order_id).merge(
user_id: current_user.id, item_id: params[:item_id], token: params[:token]
)
end

def set_order
@item = Item.find(params[:item_id])
end

def move_to_index
redirect_to root_path if current_user.id == @item.user.id || @item.order.present?
end

def pay_item
if @card.present?
Payjp.api_key = ENV['PAYJP_SECRET_KEY']
customer_token = current_user.card.customer_token
Payjp::Charge.create(
amount: @item.price,
customer: customer_token,
currency: 'jpy'
)
else
Payjp.api_key = ENV['PAYJP_SECRET_KEY']
Payjp::Charge.create(
amount: @item.price,
card: order_params[:token],
currency: 'jpy'
)
end
end
end

 if card.present?を繰り返し使っていたり、条件分岐の中に条件分岐を書いたりして読みづらくなっていたため、save_cardをprivateメソッド内で定義して呼び出すのをやめて書き直しました。

 
Payjp.api_key = ENV['PAYJP_SECRET_KEY']
 

 この記述に関しては何度も繰り返して書いているのですが、これはまとめて書いて呼び出すようにするとエラーが起きてしまったからです。

 

 以上でカード情報を登録してもしなくても商品を購入できる実装の完了です。全体的にネーミングセンスが悪く、可読性ももっと高められるはずです。しかし1箇所を修正すると全体を修正する必要性が生じたり、確認作業が増えたりするので、次の実装に生かしていこうと考えています。

 

 

 

 

 

HTTPとは

 HTTP通信とはWebアプリケーションとPC間でHTMLのような情報やデータを送受信する通信方法のことです。

 手紙を送るまでの流れに例えると、HTTP通信が書留や速達といった送り方の種類を指し、URL(Uniform Resource Locator)が送り先の住所になります。

 PC(クライアントサイド)がWebアプリケーション(サーバーサイド)に対してデータや情報を要求することを「リクエスト」と言ます。そしてWebアプリケーションがその要求された情報をPCに返却することを「レスポンス」と言います。

 

 

HTTPリクエス

 前述したようにHTTPリクエストはブラウザ(クライアントサイド)からサーバーサイドに送るものです。つまりHTTPリクエストを作るのはブラウザです。このHTTPリクエストには「HTTPリクエスト行」、「HTTPヘッダー」、「データ本体」が含まれます。

HTTPリクエスト行

 HTTPリクエストの1行目であるHTTPリクエスト行には主に「GET」というメソッド、「URL」、「HTTPのバージョン」が入っています。メソッドが「POST」(フォームから情報を送信するとき)の場合はHTTPヘッダーの後にデータ本体が続きます。

HTTPヘッダー

 2行目以降のHTTPヘッダーには、ユーザーエージェント名やクッキーなどの情報が含まれます。ユーザーエージェント名はブラウザやOSの種類であり、クッキーはログイン状態を続けるためにブラウザに保存されるデータのようなものです。他にもどのページから発生したリクエストなのかを示すリファラや、どんなデータを受け取りたいかといった情報が含まれます。

 

 

HTTPレスポンス

 HTTPレスポンスはサーバーサイドからブラウザ(クライアントサイド)に送るものであるため、サーバーが作ります。HTTPレスポンスには「レスポンス状態行(HTTPステータスコード)」、「HTTPヘッダー」、「データ本体」が含まれます。

HTTPステータスコード

 HTTPステータスコードはリクエストに対する返答の状態を示します。

100番台は処理の継続中であり、200番台は処理の成功を意味します。300番台はリダイレクト、400番台はクライアント側のエラーを表します。401は「ユーザー認証が必要」、404は「見つかりませんでした」という意味になります。そして500番台はサーバー側のエラーです。

HTTPヘッダー

 HTTPヘッダーにはコンテンツタイプやデータの最終更新日時やエンティティ情報などが含まれます。コンテンツタイプとは、データがHTMLか画像かといった情報や文字コードなどの情報を示すものです。他にも接続状況やリダイレクト先などの情報も入っています。

 

 

 自分の頭を整理する目的でHTTPについて書いてみました。こちらの記事を参考にしました。

HTTPリクエスト/レスポンスとは? HTTPヘッダーを理解しよう | 初代編集長ブログ―安田英久 | Web担当者Forum

 

 

 

 

 

 

 

 

Webサーバーとアプリケーションサーバー

 サーバーとは、Webアプリケーションの保存先であり、画面のないPCです。そのサーバーサイドの中身は大きく3つに分けられます。Webサーバー、アプリケーションサーバー、データベースサーバーです。

 その中でもWebサーバーとアプリケーションサーバーについて説明したいと思います。

 

Webサーバー

 Webサーバーとは、CSSファイルのように、リクエストのたびに内容が変更されない静的コンテンツのみをリクエストとしてクライアントに返すものです。サイトを閲覧するブラウザを指します。Webサーバーの一種としてNginx(エンジンエックス)があります。

 

アプリケーションサーバ

 アプリケーションサーバーは、リクエスト毎にデータベースから検索条件に当てはまるデータを取得して表示する役割を持つ、動的コンテンツを生成します。この処理結果をWebサーバーに返します。

 扱っているものが静的コンテンツのみの場合はWebサーバーだけでリクエストに対応してレスポンスを返します。一方でデータを扱っている場合は一旦アプリケーションサーバーを介してレスポンスするイメージだと僕は解釈しました。

 こういった処理の流れの中で、アプリケーションサーバーとアプリケーション本体は使用している言語が異なるという問題があります。この問題はRackという翻訳プログラムが解決してくれています。

 

 

 

 

 

 

ゲッターとセッター

 値の取得ができるメソッドの定義をゲッター、値の更新ができるメソッドの定義をセッターと言います。ゲッターは、クラスに設定したインスタンス変数の値をインスタンスから読み取って表示するためだけに存在します。そしてその値を更新するためのものがセッターです。

 

class Human
def initialize
puts "名前を入力してください"
@name = gets.chomp
puts "住所を入力してください"
@address = gets.to_i
end

#ゲッター
def name
@name
end

def address
@address
end

#セッター
def name=(set)
@name = set
end

def address=(set)
@address = set
end
end

 

 そしてそのゲッターとセッターの両方の役割を果たすものとして「attr_accessor」があります。attr_accessorの記述をした場合はおそらくこんな感じになります。

class Human
attr_accessor :name, :address
def initialize
puts "名前を入力してください"
@name = gets.chomp
puts "住所を入力してください"
@address = gets.to_i
end
end

 

 もし間違っていることを言っているようだったら修正いたします。

 

 

 

 

 

 

オブジェクト指向とは

 オブジェクト指向について説明します。オブジェクト指向とはデータや処理のまとまりごとに分けて実装する、設計思想の1つです。モデル、コントローラー、ビューに分けて実装することもオブジェクト指向です。

 

 ではオブジェクト指向を意識していないアプリケーションとはどのようなものだと言えるでしょうか。

 オブジェクト内に様々な役割が入り込んでいて、どこに何があるのかが分からないものや、1つの機能を変えた途端に、その変更とは関係ないはずの機能が動かなくなってしまうものなどがそうでしょう。

 オブジェクトを綺麗に切り分けなくてもとりあえず動くアプリを作ってしまったり、途中で仕様変更したり、設計思想が異なる者同士でアプリを開発したりすることでそのようなことが起きると言えます。

ユーザー新規登録時の結合テストコード

 ユーザー新規登録時の結合テストコードでやや苦戦したので紹介したいと思います。僕が苦戦したのはユーザー情報の入力です。アプリで結合テストコードを書くのは2回目だったので、初歩的な問題になります。

 

 押さえるべきポイントは以下の2点です。

 

1. fill_inでname属性を指定できる

2. 選択の場合はselectを用いる

 

1. fill_inでname属性を指定できる

 fill_inを用いるとユーザー情報を入力できます。僕が過去に結合テストコードを実行した際はfill_inでラベル名を指定していました。

app/views/devise/registrations/new.html.erb

<div class="field">
<%= f.label :nickname %> <em>(6 characters maximum)</em><br />
<%= f.text_field :nickname, autofocus: true %>
</div>

 検証ツールを用いるとlabelのfor属性と入力欄のidが一致していたため、fill_inにラベル名を指定することでテストをうまく実行できていました。

 
fill_in 'Nickname', with: @user.nickname
 

 この時はラベル名がニックネームでした。

 しかし今回の実装ではこのように記述していたため、検証ツールを用いて調べてもfor属性はありませんでした。

<div class="form-group">
<div class='form-text-wrap'>
<label class="form-text">ニックネーム</label>
<span class="indispensable">必須</span>
</div>
<%= f.text_area :nickname, class:"input-default", id:"nickname",
placeholder:"例) furima太郎", maxlength:"40" %>
</div>

 試しにこのような記述をしてみてもうまく行きませんでした。

 
fill_in 'ニックネーム', with: @user.nickname
 

 そこでラベル名以外を指定してみようと考えて、入力欄のname属性を指定するとうまく行きました。

 
fill_in 'user[nickname]', with: @user.nickname
 

 name属性を指定することでemailやpasswordなどもうまく行きました。

 

2. 選択の場合はselectを用いる

 ところが生年月日のところでつまづいてしまいました。生年月日はこのように記述していました。カラム名はbirth_dateという1つだけなのですが、実際に入力する値は年と月と日で3箇所あります。

<div class='input-birth-wrap'>
<%= raw sprintf(
f.date_select(
:birth_date,
class:'select-birth',
id:"birth-date",
use_month_numbers: true,
prompt:'--',
start_year: 1930,
end_year: (Time.now.year - 5),
date_separator: '%s'),
"<p> 年 </p>", "<p> 月 </p>") + "<p> 日 </p>" %>
</div>

 このような記述をしてもうまくいくはずがありません。

 
fill_in 'user[birth_date(1i)]', with: @user.birth_date
fill_in 'user[birth_date(2i)]', with: @user.birth_date
fill_in 'user[birth_date(3i)]', with: @user.birth_date
 

 FactoryBotで値を生成して使ってみようと試みましたが、そもそもそんなカラム名を作っていません。

 
birth_date_1i { Faker::Number.between(from: 2, to: 88) }
birth_date_2i { Faker::Number.between(from: 2, to: 13) }
birth_date_3i { Faker::Number.between(from: 2, to: 32) }
 

 自分で値を決めて入力してみてもうまく行きません。

 
fill_in 'user[birth_date(1i)]', with: 1960
fill_in 'user[birth_date(2i)]', with: 10
fill_in 'user[birth_date(3i)]', with: 10
 
 

 その時に、「あ、そもそもfill_inを使うのが間違いなんだ」と気づき、以下のように修正するとうまく行きました。

 
select '1960',from: 'user[birth_date(1i)]'
select '10',from: 'user[birth_date(2i)]'
select '10',from: 'user[birth_date(3i)]'
 

 これで後は問題なく新規登録時のテストはうまく作動しました。

 

 

 このような初歩的なことに時間を使わないように気をつけましょう。

 

 

 

 

アジャイル型開発とは

 開発手法には大きく分けて、アジャイル型開発とウォーターフォール型開発があります。アジャイル型開発は利用者の反応を見ながら少しずつ開発していくものであり、ウォーターフォール型開発は最初に決めた要件を、期限までに完了させる手法です。

 

 アジャイル型開発は進捗が把握しづらく、ウォーターフォール型開発は仕様変更に対応しにくいといったデメリットがあります。実際に使ってみないと分からない機能がある場合はアジャイル型開発が有効であり、多くのエンジニアが関わり、役割分担が必要な場合はウォーターフォール型開発が有効です。

 

 このようにプログラムを管理する上で使えるツールには、Siderがあります。SiderはGitHubと連携してコードレビューを自動で行ってくれます。

 

 リリースの頻度が多いアジャイル型開発では、CI/CDを導入して変更したコードの自動チェックを行うことで人的負担を少なくすることができます。

 

 

 

クラスとインスタンス

 クラスとインスタンスについて説明します。クラスとインスタンスとは新しい種類の値を作る仕組みのことです。

 

クラスとは

 クラスを1言で言うと設計図です。このクラスで共通の属性と処理(メソッド)のルールを決めます。

 

インスタンスとは

 インスタンスを1言で言うとデータです。クラスを元にして作られます。このインスタンスはクラスが使用できるnewメソッドで生成されます。インスタンスを生成する時は、多くの場合、後からデータを追加したり、メソッドを実行できるようにしたりするために、変数に代入します。