11
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

はじめに

社員の皆さんはこんな奴が最近エンジニアになって頑張ってるんだなと暖かい目で読んでいただければと思います。

社外の方やエンジニアを目指している方は少しでも学習の参考や、コネクター・ジャパンに興味を持っていただければと思います。

自己紹介

未経験から独学でプログラミング学習し5ヶ月でLaravelでポートフォリオを作成しました。そして現在は自社開発企業に入社し、WEBエンジニアとしてプロダクト開発に携わっています。

この記事を書いた理由

エンジニアなりたての初心者の頃は、コードがごちゃごちゃになりがちでした。
しかし、オブジェクト指向の基本原則であるSOLID原則を学ぶことで、すっきりとしたコードを意識して書くようになりました。

オブジェクト指向は、うまく扱うことが出来れば保守性が上がり、修正対応や機能を新しく追加する時などに楽に対応できるようになります。

つまりコードの品質を保ちやすくなるんですよね。

しかしなかなか理解が難しいので、今回は私なりにプログラムをきれいに保つための「SOLID原則」を、初心者の方でも理解しやすいようにわかりやすい言葉で置き換えて、PHPを使って簡単な例で解説します。

それでは、一つずつ見ていきましょう!

記事の流れ

  1. SOLID原則って何?
  2. S: 一つのことに集中しよう(単一責任の原則)
  3. O: 柔軟に拡張できるように(オープン/クローズドの原則)
  4. L: 代わりにもなれるように(リスコフの置換原則)
  5. I: 必要なものだけを使おう(インターフェース分離の原則)
  6. D: 上手に頼り合おう(依存性逆転の原則)
  7. まとめ

1. SOLID原則って何?

SOLID原則とは、プログラムを「きれい」に保つための5つのお約束です。これを守ることで、プログラムがごちゃごちゃにならずに済み、後で読んだり変更したりするときに楽になります。

以下の5つの原則の頭文字をとったものです。

  • S: Single Responsibility Principle(単一責任の原則)
  • O: Open/Closed Principle(オープン/クローズドの原則)
  • L: Liskov Substitution Principle(リスコフの置換原則)
  • I: Interface Segregation Principle(インターフェース分離の原則)
  • D: Dependency Inversion Principle(依存性逆転の原則)

これらの原則を理解し適用することで、コードはより柔軟で、読みやすく、そしてメンテナンスしやすいものになります。

2. S: 一つのことに集中しよう(単一責任の原則)

「一つのクラスは一つのことだけに集中すべき」というお約束です。例えば、あるクラスが「料理を作ること」と「注文をとること」の二つをしていたら、それは一つのことに集中していないですよね。料理と注文は別々のクラスにすると、もっと管理しやすくなります。

// 単一責任の原則に反している例
class Restaurant {
    public function prepareFood() {
        return "料理を作る";
    }
    
    public function takeOrder() {
        return "注文をとる";
    }
}

// 単一責任の原則に従った例
class Chef {
    public function prepareFood() {
        return "料理を作る";
    }
}

class Waiter {
    public function takeOrder() {
        return "注文をとる";
    }
}

3. O: 柔軟に拡張できるように(オープン/クローズドの原則)

「拡張には開いているが、変更には閉じている」というお約束です。これは、新しい機能を追加したいときに、既存のコードをいじらずに済むようにしようということです。新しいものを追加するだけで、前のものはそのままにしておける、そんな設計を心がけましょう!

// オープン/クローズドの原則に反している例
class Shape {
    public function draw() {
        // 描画のロジック
    }
}

// オープン/クローズドの原則に従った例
abstract class Shape {
    abstract public function draw();
}

class Circle extends Shape {
    public function draw() {
        return "円を描く";
    }
}

class Square extends Shape {
    public function draw() {
        return "四角を描く";
    }
}

4. L: 代わりにもなれるように(リスコフの置換原則)

あるクラスが別のクラスの「代わり」になれるようにしようというお約束です。サブクラスは、そのスーパークラス(あるクラスの仕様を継承して新しいクラスを作成する際に、元となるクラス)と置き換え可能でなければなりません。例えば、「鳥」クラスがあり、それを継承して「ペンギン」クラスを作ったとします。でもペンギンは飛べないので、「鳥」クラスの「飛ぶ」機能はペンギンには合いません。こういう「合わない」ことがないようにしましょう。

// リスコフの置換原則に反している例
class Bird {
    public function fly() {
        return "飛ぶ";
    }
}

class Ostrich extends Bird {
    public function fly() {
        throw new Exception("ダチョウは飛べない");
    }
}

// リスコフの置換原則に従った例
class Bird {
}

class FlyingBird extends Bird {
    public function fly() {
        return "飛ぶ";
    }
}

class Ostrich extends Bird {
    // ダチョウは飛ばないので、flyメソッドは持たない
}

5. I: 必要なものだけを使おう(インターフェース分離の原則)

大きな一つのインターフェースよりも、小さくて特定の目的に特化したインターフェースを複数作るべきだという原則です。これにより、クラスは必要のないメソッドに依存することなく、必要なものだけを使うことができます。

// インターフェース分離の原則に反している例
interface WorkerInterface {
    public function work();
    public function eat();
}

class HumanWorker implements WorkerInterface {
    public function work() {
        // 仕事をする
    }
    
    public function eat() {
        // 食事をする
    }
}

class RobotWorker implements WorkerInterface {
    public function work() {
        // 仕事をする
    }
    
    public function eat() {
        // ロボットは食事をしない
    }
}

// インターフェース分離の原則に従った例
interface WorkableInterface {
    public function work();
}

interface EatableInterface {
    public function eat();
}

class HumanWorker implements WorkableInterface, EatableInterface {
    public function work() {
        // 仕事をする
    }
    
    public function eat() {
        // 食事をする
    }
}

class RobotWorker implements WorkableInterface {
    public function work() {
        // 仕事をする
    }
    // eatメソッドは不要なので実装しない
}

6. D: 上手に頼り合おう(依存性逆転の原則)

依存性逆転の原則は、コードの柔軟性を高めるために「具体ではなく抽象に依存しよう」というお約束です。これは、クラスが他のクラスに強く依存してしまうと、変更がとても難しくなるため、依存する側を抽象化して柔軟にしましょうということです!

// 依存性逆転の原則に反している例
class MySQLConnection {
    public function connect() {
        // MySQLへの接続の詳細
        return "MySQLに接続";
    }
}

class PasswordReminder {
    private $dbConnection;

    public function __construct(MySQLConnection $dbConnection) {
        $this->dbConnection = $dbConnection;
    }
    // ...
}

// 依存性逆転の原則に従った例
interface DatabaseConnectionInterface {
    public function connect();
}

class MySQLConnection implements DatabaseConnectionInterface {
    public function connect() {
        // MySQLへの接続の詳細
        return "MySQLに接続";
    }
}

class PasswordReminder {
    private $dbConnection;

    public function __construct(DatabaseConnectionInterface $dbConnection) {
        $this->dbConnection = $dbConnection;
    }
    // ...
}

7. まとめ

わかりやすく説明するためにざっくりとした内容になってしまったかもしれません。
もっとしっかりと学びたいという方は、田中ひさてるさんが書いたこちらの書籍をお勧めします。

ちょうぜつソフトウェア設計入門――PHPで理解するオブジェクト指向の活用

私自身も記事を書いててまだまだ勉強しなきゃいけないなと思いました。理解を深めていきたいと思います。

このお約束事を少し覚えておくだけでも、コードを書く意識の仕方がかなり変わるのと思うので参考になっていれば嬉しいです!

一緒に働く仲間を募集しています!

株式会社コネクター・ジャパンでは一緒に働いてくれる仲間を募集しています!

事業拡大に伴い、エンジニアさんを大募集しています。
興味のある方は下記リンクから弊社のことをぜひ知っていただき応募してもらえると嬉しいです。
▼会社について
https://www.wantedly.com/companies/cnctor/about
▼代表メッセージ
https://cnctor.jp/10years-anniversary/
▼応募はこちら
https://www.wantedly.com/projects/1568084

質問があればお気軽にXでDMお送りください!

11
7
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
7

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?