うまとま君の技術めも

2015年新卒入社した社畜の勉強内容などなど

アジャイル検定Lv.2 勉強メモ - チームのスキル

アジャイル検定Lv.2 出題範囲

チームのスキル

スプリント計画

  • スプリントの作業を計画する
  • スプリント計画では以下の質問に答える
    • スプリントの成果物として何を作るか?
    • スプリントの成果物を作るために必要な作業をどのように成し遂げるか?

レトロスペクティブ

  • 次のスプリントの改善計画を作成する
    • 人・関係・プロセス・ツールの観点から振り返る
    • 成功したこと・失敗したこと・改善点を整理する
    • チームの作業を改善するための実施計画を作る

自己組織化されたチーム

  • 自己組織化
    • 自己組織化はチームが形成され、ある問題と制約が与えられたら、どのようにその問題を解決するかをチームが自分たちで決めるということ
  • 継続的改善
    • 自己組織化されたチームは最初のプロセスを忠実に守り、一定期間後に振り返りを行う
    • 失敗したこと・成功したこと・改善点が何かを考え、その結果に従ってプロセスを変えていく
  • 自己組織化されたチーム
    • 監督役を必要としない。外からタスクが割り当てられないし、進捗もチェックされない
    • プロジェクト・プロダクトに関する全ての情報を知ろうとする
    • 仕事に誇りを持ち、責任を引き受ける
    • 目的を与えられ、どのように目的に向かっているかを見られる
    • チームのルールを決め、そのルールに従う
    • 様々なタスクを解決し、メンバーの全ての専門性を活用する
    • 進捗を監視し管理する
  • 自己組織化されたチームを作るには

参考資料

アジャイル検定Lv.2 勉強メモ - デザインパターン

アジャイル検定Lv.2 出題範囲

デザインパターン

デザインパターン

  • よく出会う問題とそれにうまく対処するためのソフトウェア設計をパターン化し、再利用しやすい形に整理したもの
  • メリット
    • 再利用性の高い柔軟な設計ができる
    • 技術者どうしの意思疎通が容易になる

GoFデザインパターン

  • 生成に関するパターン
    • Abstract Factory
    • Builder
    • Factory Method
    • Prototype
    • Singleton
  • 構造に関するパターン
    • Adapter
    • Bridge
    • Composite
    • Decorator
    • Facade
    • Flyweight
    • Proxy
  • 振る舞いに関するパターン
    • Chain of Responsibility
    • Command
    • Interpreter
    • Iterator
    • Mediator
    • Memento
    • Observer
    • State
    • Strategy
    • Template Method
    • Visitor

Abstract Factory

  • 関連したオブジェクトを間違いなく生成するためのパターン
interface Factory {
  getSoup(): object
  getVegetables(): object
}
class KimuchiFactory implements Factory {
  getSoup(): object { return 'キムチスープ' }
  getVegetables(): object { 'キムチ,しめじ' }
}
class Pot {
  addSoup(soup: object) { /* ... */ }
  addVegetables(vegetables: object) { /* ... */ }
}
function createFactory(type: string): Factory {
  if (type === 'キムチ鍋') {
    return new KimuchiFactory()
  } else {
    return /* ... */
  }
}
function main() {
  const factory = new createFactory('キムチ鍋')
  const pot = new Pot()
  pot.addSoup(factory.getSoup())
  pot.addVegetables(factory.getVegetables())
}

Builder

  • オブジェクトの作成過程をコントロールするためのパターン
interface Builder {
  makeTitle();
  makeString();
  close();
  getResult<T>(): T;
}
class Director {
  constructor(builder: Builder) {
    this.builder = buidler;
  }
  construct() {
    this.builder.makeTitle('場所');
    this.builder.makeString('東京都港区 1-1-1');
    this.builder.makeTitle('日時');
    this.builder.makeString('2999/01/23');
    close();
  }
}
function main() {
  const builder = new HtmlBuilder();
  const director = new Director(builder);
  director.construct();
  const html = builder.getResult<Html>();
}

Factory Method

  • 柔軟にオブジェクトを生成するためのパターン
abstract class Factory {
  abstract createAccount(name: string): Account;
  create(name: string): Account {
    const account = new createAccount(name)
    return account;
  }
}
interface Account {
  type: string;
  name: string;
}
class AdminFactory extends Factory {
    createAccount(name: string): Account {
      const account = new Account();
      account.type = 'admin';
      account.name = name;
      return account;
    }
}
function main() {
  const factory = new AdminFactory();
  const admin1 = factory.create('山田 太郎');
  const admin2 = factory.create('佐藤 次郎');
}

Prototype

  • あらかじめ用意しておいた「原型」からインスタンスを生成するようにするためのパターン
interface Clonable {
  createClone(): Clonable;
}
class Manager {
  hashMap: Map = new Map();
  register(name: string, cloneable: Clonable) {
     this.hashMap[name] = cloneable;
  }
  create(name: string): Clonable {
    return this.hashMap[name].createClone();
  }
}
function main() {
  const manager = new Manager();
  manager.register('class a', new ClassA());
  manager.register('class b', new ClassB());

  const a = manager.create('class a') as ClassA;
  const b = manager.create('class b') as ClassB;
}

Singleton

class Singleton {
  static singleton: Singletone = new Singletone();
  private constructor() {}
  getInstance() {
    return this.singleton;
  }
}

Adapter

  • インタフェースに互換性の無いクラス同士を組み合わせることを目的としたパターン
interface Student {
  getFullName(): string;
}
class Child {
    constructor(firstName: string, lastName: string) {
      this.firstName = firstName;
      this.lastName = lastName;
    }
}
// 継承を利用したパターン
class ChildAdapter extends Child implements Student {
  getFullName(): string {
    return `${this.firstName} ${this.lastName}`;
  }
}
// 委譲を利用したパターン
class ChildAdapter implements Student {
  constructor(firstName: string, lastName: string) {
    this.child = new Child(firstName, lastName);
  }
  getFullName(): string {
    return `${this.child.firstName} ${this.child.lastName}`;
  }
}
function main() {
  const student = new ChildAdapter('Taro', 'Yamada')
  student.getFullName();
}

Bridge

  • 機能を拡張するクラスと実装を拡張するクラスを分けるためのパターン
class Sorter {
  constructor(sortImpl: SortImpl) {
    this.sortImpl = sortImpl
  }
  sort(array: Array) {
    this.sortImpl.sort(array);
  }
}
class ImmutableSorter {
  immutableSort(array: Array): Array {
    const clonedArray = array.clone();
    return this.sortImple.sort(clonedArray);
  }
}
interface SortImpl {
  sort();
}
class QuickSortImpl implements SortImpl {
  sort() { /* クイックソート処理 */ }
}
class BubbleSortImpl implements BubbleSortImpl {
  sort() { /* バブルソート処理 */ }
}
function main() {
  new Sorter(new QuickSortImpl()).sort([5,1,2])
  new Sorter(new BubbleSortImpl()).sort([5,1,2])

  const arr1 = new ImmutableSorter(new QuickSortImpl()).immutableSort([5,1,2])
  const arr2 = new ImmutableSorter(new BubbleSortImpl()).immutableSort([5,1,2])
}

Composite

  • 容器と中身を同一視することで再帰的な構造を扱いやすくするためのパターン
interface Entry {
  getName(): string;
  remove();
}
class File implements Entry {
  constructor(name: string) { this.name = name }
  getName(): string { return this.name }
  remove() { console.log(`${this.getName()}を削除しました`) }
}
class Directory implements Entry {
  constructor(name: string) {
    this.name = name
    this.entries = []
  }
  getName(): string { return this.name }
  remove() {
    for (const entry of this.entries) {
      entry.remove()
    }
    console.log(`${this.getName()}を削除しました`)
  }
  add(entry: Entry) {
    this.entries.push(entry)
  }
}
function main() {
  const rootDir = new Directory('root')
  const homeDir = new Directory('home')

  homeDir.add(new File('.bashrc'))
  rootDir.add(homeDir)
  rootDir.remove()
}

Decorator

  • 飾り枠と中身を同一視することで、柔軟に機能拡張しやすくするためのパターン
interface Ice {
  getName(): string
}
class VanillaIce implements Ice {
  getName(): string { return 'バニラアイス' }
}
class NutsToppingIce implements Ice {
  constructor(ice: Ice) { this.ice = ice }
  getName(): string {
    return `ナッツ ${this.ice.getName()}`
  }
}
class ChocoToppingIce implements Ice {
  constructor(ice: Ice) { this.ice = ice }
  getName(): string {
    return `チョコ ${this.ice.getName()}`
  }
}
function main() {
  new VanillaIce().getName() // バニラアイス
  new NutsToppingIce(new VanillaIce()).getName() // ナッツ バニラアイス
  new ChocoToppingIce(new NutsToppingIce(new VanillaIce())).getName() // チョコ ナッツ バニラアイス
}

Facade

  • 複数クラス組み合わせて行う処理を、窓口となるクラスを作ってシンプルに利用できるようにするためのパターン
  class HtmlWriter {
    setTitle(title: string) { this.title = title }
    setBody(body: string) { this.body = body }
    output(): string {
      return `<html>
                <head>${this.title}</head>
                <body>${this.body}</body>
              </html>`
    }
  }
  class FileWriter {
    create(file: string, content: string) { /* ファイル書き込み処理 */ }
  }
  class PageMaker {
    makeWelcomePage(title: string, file: string) {
      const htmlWriter = new HtmlWriter()
      htmlWriter.setTitle(title)
      htmlWriter.setBody(`ようこそ ${title} へ!!`)

      const fileWriter = new FileWriter()
      fileWriter.create(file, fileWriter.output())
    }
  }
  function main() {
    const pageMaker = new PageMaker()
    pageMaker.makeWelcomePage('ABC', 'welcome.html')
  }

Flyweight

  • インスタンスを共有することでリソースを無駄なく使うためのパターン
class Stamp {
  constructor(value: string) { this.value = value }
  print() { console.log(this.value) }
}
class StampFactory {
  stamps = {}
  get(value: string): Stamp {
    if (!this.stamps[value]) {
      this.stamps[value] = new Stamp(value)
    }
    return this.stamps[value]
  }
}
function main() {
  const factory = new StampFactory()
  const stamps = [
    factory.get('a'),
    factory.get('p'),
    factory.get('p'),
    factory.get('l'),
    factory.get('e'),
  ]
  for (const stamp of stamps) {
    stamp.print()
  }
}

Proxy

  • 作業に時間がかかっているオブジェクトの代わりに
interface Image {
  render()
}
class RealImage implements Image {
  constructor(path: string) { /* 画像読み込み処理 */ }
  render() { /* 画像を表示 */ }
}
class LazyLoadImage implements Image {
  constructor(path: string) { this.path = path }
  render() {
    const realImage = new RealImage(path)
    realImage.render()
  }
}
function main() {
  const image1 = new LazyLoadImage('image1.png')
  const image2 = new LazyLoadImage('image2.png')
  const image3 = new LazyLoadImage('image3.png')

  image1.render() // 画像が読み込まれ表示される
  image2.render() // 画像が読み込まれ表示される
  // image3の不要な読み込み処理は行われない
}

Chain of Responsibility

  • 「責任者」を「鎖状」につないでおき、「いずれかの段階」で、「誰か」が処理をすることを表現するためのパターン
abstract class Responsible {
  setNext(next: Responsible) { this.next = next }
  salaryRaise(score: int): boolean {
    if (this.isMoreThanExpected(store)) {
      if (this.next) {
        return this.next.salaryRaise()
      } else {
        return true
      }
    } else {
      return false
    }
  }
  abstract isMoreThanExpected(store: int): boolean
}
class Staff extends Responsible {
  isMoreThanExpected(score: int) {
    return score > 50
  }
}
class TeamLeader extends Responsible {
  isMoreThanExpected(score: int) {
    return score > 70
  }
}
class Manager extends Responsible {
  isMoreThanExpected(score: int) {
    return score > 90
  }
}
function main() {
  const staff = new Staff()
  const teamLeader = new TeamLeader()
  const manager = new Manager()

  staff.setNext(teamLeader).setNext(manager)
  staff.salaryRaise(80) // false
  staff.salaryRaise(95) // true
}

Command

  • 要求をCommandオブジェクトにして、それらを複数組み合わせて使えるようにするパターン
interface Command {
  execute()
}
class SaladCommand implements Command {
  execute() { /* サラダを調理 >> 提供 */ }
}
class CurryCommand implements Command {
  execute() { /* カレーを調理 >> 提供 */ }
}
class SoupCommand implements Command {
  execute() { /* スープを調理 >> 提供 */ }
}
class Order {
  constructor() {
    this.commands = []
  }
  add(command: Command) {
    this.commands.push(command)
  }
  confirm() {
    for (const command of this.commands) {
      command.execute()
    }
  }
}
function main() {
  const order = new Order()
  order.add(new SaladCommand())
  order.add(new CurryCommand())
  order.add(new SoupCommand())
  order.confirm()
}

Interpreter

Iterator

  • 要素の集まりを保有するオブジェクトの各要素に順番にアクセスする方法を提供するためのパターン
interface Iterator {
  hasNext(): boolean
  next(): any
}
interface Aggregate {
  iterator(): Iterator
}
class UserListIterator implements Iterator {
  index: 0
  constructor(userList: UserList) { this.userList = userList }
  hasNext(): boolean { return (index < users.getSize()) }
  next(): any { return this.getAt[index++] }
}
class UserList implements Aggregate {
  users: []
  add(user: string) { this.users.push(user) }
  getSize(): int { return this.users.length }
  getAt(index): string { this.users[index] }
  iterator(): Iterator { return new UserListIterator(this) }
}
function main() {
  const userList = new UserList()
  userList.add ('田中')
  userList.add('佐藤')
  userList.add('山田')

  const iterator = userList.iterator()
  while (iterator.hasNext()) {
    console.log(iterator.next())
  }
}

Mediator

  • 複数のオブジェクト間の調整をするために、仲介役のクラスを利用するパターン
interface ChatRoomMediator {
  showMessage(user: User, message: string)
}
class ChatRoom implements ChatRoomMediator {
  showMessage(user: User, message: string) {
    console.log(user.name, message)
  }
}
class User {
  constructor(name: string, mediator: Mediator) {
    this.name = name
    this.mediator = mediator
  }
  send(message: string) {
    this.mediator.showMessage(this, message)
  }
}
function main() {
  const mediator = new ChatRoom()

  const tom = new User('Tom', mediator)
  const bob = new User('Bob', mediator)

  tom.send('Hello')
  bob.send('Hi')
}

Memento

  • インスタンスの状態を保存し、後から状態を復元するためのパターン
class EditorMemento {
  constructor(content: string) { this.content = content }
  getContent() { return this.content }
}
class Editor {
  content = ''
  type(text: string) { this.content += text }
  getContent(): string { return this.content }
  save(): EditorMemento { return new EditorMemento(this.content) }
  restore(mement: EditorMemento) { this.content = mement.getContent() }
}
function main() {
  const editor = new Editor()

  editor.type('abc')
  editor.type('def')
  const saved = editor.save()

  editor.type('ghi')
  editor.getContent() // abcdefghi

  editor.restore(saved)
  editor.getContent() // abcdef
}

Observer

  • 通知の仕組みをより汎用的に利用できる形で提供するためのパターン
interface Observer {
  update(jobPost: string)
}
class JobSeeker implements Observer {
  update(jobPost: string) {
    console.log(`${jobPost}の求人が追加されました`)
  }
}
interface Subject {
  notify(jobPost: string)
}
class JobPostings implements Subject {
  attach(jobSeeker: JobSeeker) { this.jobSeekers.push(jobSeeker) }
  addJob(jobPost: string) { this.notify(jobPost) }
  notify(jobPost: string) {
    for (const jobSeeker of this.jobSeekers) {
      jobSeeker.update(jobPost)
    }
  }
}
function main() {
  const jobSeeker = new JobSeeker()
  const jobPostings = new JobPostings()
  jobPostings.attach(jobSeeker)

  jobPostings.addJob('エンジニア') // エンジニアの求人が追加されました
  jobPostings.addJob('デザイナー') // デザイナーの求人が追加されました
}

State

  • 状態に応じて振る舞いを変化させるためのパターン
interface State {
  write(text: string)
}
class UpperCaseState implements State {
  write(text: string) { console.log(text.toUpperCase()) }
}
class LowerCaseState implements State {
  write(text: string) { console.log(text.toLowerCase()) }
}
class TextEditor {
  setState(state: State) { this.state = state }
  type(text: string) { this.state.write(text) }
}
function main() {
  const editor = new TextEditor()

  editor.setState(new UpperCaseState())
  editor.type('Hello World') // HELLO WORLD

  editor.setState(new LowerCaseState())
  editor.type('Hello World') // hello world
}

Strategy

interface SortStrategy {
  sort(array: [])
}
class BubbleSortStrategy implements SortStrategy {
  sort(array: []) { /* バブルソート処理 */ }
}
class QuickSortStrategy implements SortStrategy {
  sort(array: []) { /* クイックソート処理 */ }
}
class Sorter {
  constructor(strategy: SortStrategy) { this.strategy = strategy }
  sort(array: []) { this.strategy.sort(array) }
}
function main() {
  const array = [1, 5, 3, 2]

  const sorter1 = new Sorter(new BubbleSortStrategy())
  sorter1.sort(array)

  const sorter2 = new Sorter(new QuickSortStrategy())
  sorter2.sort(array)
}

Template Method

  • スーパークラスで処理の枠組みを定め、サブクラスでその具体的内容を実装するパターン
abstract class AppBuilder {
  build() {
    this.test()
    this.assemble()
    this.deploy()
  }
  abstract test()
  abstract assemble()
  abstract deploy()
}
class AndroidBuilder extends AppBuilder {
  test() { /* Androidテスト処理 */ }
  assemble() { /* Androidアセンブル処理 */ }
  deploy() { /* Androidデプロイ処理 */ }
}
class IosBuilder extends AppBuilder {
  test() { /* iOSテスト処理 */ }
  assemble() { /* iOSアセンブル処理 */ }
  deploy() { /* iOSデプロイ処理 */ }
}
function main() {
  const androidBuilder = new AndroidBuilder()
  androidBuilder.build()

  const iosBuilder = new IosBuilder()
  iosBuilder.build()
}

Visitor

  • 受け入れる側に処理を追加することなく、処理を追加することができるパターン
interface AnimalOperation {
  visitMonkey(monkey: Monkey)
  visitLion(lion: Lion)
}
interface Animal {
  accept(operation: AnimalOperation)
}
class Monkey implements Animal {
  shout() { console.log('ウキャッ、キャッ') }
  accept(operation: AnimalOperation) {
    operation.visitMonkey(this)
  }
}
class Lion implements Animal {
  roar() { console.log('ガオォオオ') }
  accept(operation: AnimalOperation) {
    operation.visitLion(this)
  }
}
class BarkOperation implements AnimalOperation {
  visitMonkey(monkey: Monkey) {
    monkey.shout()
  }
  visitLion(lion: Lion) {
    lion.roar()
  }
}
function main() {
  const bark = new BarkOperation()

  const monkey = new Monkey()
  monkey.accept(bark)

  const lion = new Lion()
  lion.accept(bark)
}

SOLID原則

  • Single responsibility principle
    • あるモジュールやクラスや関数などを改修する理由はたった1つになるようにする
    • 1つのクラスが複数の役割を持っている→変更時に他の役割にも影響を与えてしまう
  • Open-closed principle
    • 拡張に対してオープンで、修正に対してクローズドにする
    • 機能を追加する時に既存コードの修正が必要→既存の振る舞いが変わってしまう
  • Liskov substitution principle
    • 子クラスは親クラスと置き換え可能にする
    • 置換可能でない→抽象以外に依存している→密結合になってしまう
  • Interface segregation principle
    • インターフェースを複雑にしてはいけないので、分離できるものは分離する
    • インターフェースが複雑→複数の役割を持っている→変更時に受ける影響が大きくなる
  • Dependency inversion principles
    • 依存方向を逆転させることで、設計上望ましい依存の方向性にする
    • 望ましい依存の仕方→双方向依存しない・依存関係が循環しない・必要以上の情報を受け取らず疎結合

UML(Unified Modeling Language)

  • ソフトウェアの機能や構造を表す「図」の描き方
  • モデリング
    • 言葉で表現しきれない抽象的・複雑・あいまいな対象を、目的に合わないもの除きシンプルにした上で、「模型」や「図」など視覚的に表現すること
  • ダイアグラム
    • 構造
      • クラス図
        • クラス間の関係や、各クラスの変数などを表現したもの
      • 複合構造図
      • コンポーネント
      • オブジェクト図
      • パッケージ図
        • パッケージ間の関係を表現したもの
    • 振る舞い
      • ユースケース
        • システムが提供する機能と利用者の関係を表現したもの
      • アクティビティ図
        • 一連の処理における制御の流れを表現したもの
      • ステートマシン図
    • 相互作用
      • シーケンス図
        • オブジェクト間の連携や動作の流れを表現したもの
      • コミュニケーション図
      • 相互作用概要図
      • タイミング図
ダイアグラム名 サンプル
クラス図 f:id:umatomakun:20200125123547g:plain
オブジェクト図 f:id:umatomakun:20200125123606g:plain
パッケージ図 f:id:umatomakun:20200125123618p:plain
ユースケース f:id:umatomakun:20200125123629j:plain
アクティビティ図 f:id:umatomakun:20200125123642j:plain
シーケンス図 f:id:umatomakun:20200125123654g:plain
コミュニケーション図 f:id:umatomakun:20200125123706g:plain

参考資料

アジャイル検定Lv.2 勉強メモ - 常時結合

アジャイル検定Lv.2 出題範囲

常時結合

CI/CD

  • アプリケーション開発のステージに自動化を取り入れて、顧客にアプリケーションを提供する頻度を高める手法

継続的インテグレーション(CI)

  • ビルドと単体テストおよび統合テストを自動化
  • 単体テストと統合テストを行い、変更によってアプリケーションが破壊されないことを確認する
  • CIを利用するとコンフリクトやバグをすばやく容易に、高頻度で修復できる

継続的デリバリー(CD)

  • 検証されたコードのリポジトリへのリリースを自動化
  • 開発者によるアプリケーションへの変更をリポジトリにアップロードする
  • 本番環境にデプロイできるコードベースを常に保持しておくことを目的とする
  • プロセスの終了時には、運用チームはアプリケーションを本番環境にすばやく簡単にデプロイできる

継続的デプロイメント(CD)

  • アプリケーションの番環境へのリリースを自動化
  • 開発者による変更をリポジトリから本番環境に自動的にリリースし、顧客が使用できるようにする
  • ユーザーからのフィードバックを継続的に受け取って反映することが簡単になる

参考資料

アジャイル検定Lv.2 勉強メモ - テスト

アジャイル検定Lv.2 出題範囲

テスト

テスト駆動開発(TDD)

  • 「動作するきれいなコード」を書くのが目的
  • TDDサイクル
    • Red → Green → Refactor
    • テストを書く → 動かす → 正しくする

モックを使ったテスト

コードカバレッジ

  • ユニットテストの品質基準
    • C0(命令網羅)
      • プログラム中の全ての命令が1回以上実行を測定
    • C1(分岐網羅)
      • プログラム中の各分岐について1回以上実行を測定
    • C2(条件網羅)
      • プログラム中の判定の組み合わせを測定

テスト技法

  • ホワイトボックステスト
    • 内部ロジックや仕様を考慮してテストケースを設計
    • 内部仕様の細かい粒度で検証するテストで使われる
  • ブラックボックステスト
    • 外部仕様からテストケースを設計
    • 機能単位などの大きな粒度で検証するテストで使われる

アジャイルテストの4象限 f:id:umatomakun:20200117234311p:plain

参考資料

アジャイル検定Lv.2 勉強メモ - 構成管理

アジャイル検定Lv.2 出題範囲

構成管理

ソフトウェア構成管理(SCM)

ブランチ戦略

  • ブランチを利用したバージョン管理ワークフロー
  • git-flow
    • 大規模な構成
    • デスクトップ・モバイルアプリのように「リリース」を必要とするソフトウェアの開発に適している
    • ブランチ一覧
      • メインブランチ
      • サポートブランチ
        • feature:開発作業用
        • release:リリース作業用
        • hotfix:緊急修正用
  • github-flow
    • 小規模な構成
    • 1日に複数回デプロイを行うようなWebアプリケーションの開発に適している
    • ブランチ一覧
git-flow github-flow
f:id:umatomakun:20200116195948j:plain f:id:umatomakun:20200116200113j:plain

コンテナ技術

  • コンテナとは
    • ホストOS上の独立したアプリケーション実行環境
  • 仮想マシンとコンテナ
    • 仮想マシン
      • 仮想的なハードウェア環境
      • OSやアプリケーションをインストールし、独立した実行環境を構築する
      • e.g. VMWare, VirtualBox
    • コンテナ
      • OSリソースを隔離・制限したプロセス
      • OSリソースが隔離・制限された環境でアプリケーションを実行し、独立した実行環境を構築する
      • e.g. Docker
  • メリット
    • コードベースでインフラ定義できる
    • どの環境でも同じ様に動く
    • インフラの構成管理やデプロイが行いやすい

参考資料

アジャイル検定Lv.2 勉強メモ - コーディング

アジャイル検定Lv.2 出題範囲

コーディング

コーディングルール(コーディング規約)

  • プログラムの書き方に関するガイドラインを定めたもの
  • 可読性を高めることができる
    • 可読性を高めることで 保守性・品質 の向上が期待できる

静的解析ツール

  • 機械的にコーディングルールなどをチェックすることが出来る
  • Linter
  • SonorQube
    • OSSの品質管理プラットフォーム
    • 不具合・脆弱性を検出したり、複雑度を確認したりすることが出来る

ペアプログラミング

  • 2人で1つのコンピュータを使って共同作業を行う
  • 品質向上・スキルアップ・素早い情報伝達などが期待できる

リーダビリティ(可読性)

  • 読みにくいコードを書くと?
    • 理解しづらい → 変更に時間がかかる → 変更に柔軟に対応できない
  • 読みやすいコード書くには?

テストコード

ドキュメンテーション

  • プログラムの使い方などをまとめたドキュメント
  • 自動生成ツール

参考資料

アジャイル検定Lv.2 勉強メモ - モデリング

アジャイル検定Lv.2 出題範囲

オブジェクト指向設計

オブジェクト指向設計とは?

  • システムがどのように構築されるかをオブジェクトの集合としてモデル化したもの
    • オブジェクト
      • 何かしらの概念を表現したもの
      • データ構造や処理を実行するメソッドによって構成される

なぜオブジェクト指向設計を用いるのか?

  • 変更に対して柔軟に対応するため
    • 頻繁に変更される部分を抽出することで変更に対応する
      • 変更される部分 → クラス
      • 変更されない部分 → インターフェース

継承・ポリモーフィズムカプセル化

  • オブジェクト指向設計を行う上で重要となってくる3つの要素
    • 継承
      • 交換可能なパーツの規格を抽象概念として定義し、規格を元に様々な種類のパーツを作成すること
        • インターフェースから派生したクラスを作成する
    • ポリモーフィズム
      • 抽象概念に対してプログラミングすること
      • e.g. Animal animal = new Dog(); animal.bark();
    • カプセル化
      • 外から見てシンプルで使いやすいものを作ること
        • 役割を1つにする・分かりやすい命名 が重要となってくる

疎結合

  • 抽象に依存することで、依存先への影響を受けにくくする
    • インターフェースに依存する

Dependency Injection

  • インスタンス生成時にクラスに依存してしまう問題を解決する事ができる

参考資料