静的型付け言語・動的型付け言語

(会社のLT会で発表したものの転記。)

TypeScriptのメリットを紹介するつもりでしたが、型がある言語全般に言えることなので、もう少し広い意味で静的型付け言語・動的型付け言語の紹介をします。

データ型

データ型・プログラムを実行するときのデータの入れも(コンピュータのメモリの確保する量)

データ型を定義する→プロダクトの実行前に入れ物の大きさが分かる→データに対して最適なメモリ使用量で済む

データ型を定義しない→プログラム実行前に入れ物の大きさが分からない→実行するまでにどんなデータが来るか分からないため、余分にメモリを確保する必要がある

※メモリ=一時的にデータを記憶する場所、作業机のイメージ

机のスペースが広い=メモリの使用量が少ない→実行速度が速い
机のスペースが狭い=メモリの使用量が多い→実行速度が遅い

特徴

静的型付け言語

変数・関数にデータ型の宣言が必要な言語

  • メリット
    • データ型に関するエラーが事前に分かる
    • 実行速度が速い
  • メリット
    • コードの記述量が多い
    • 開発スピードが遅い

言語

動的型付け言語

変数・関数にデータ型の宣言が不要な言語

  • メリット
    • コードの記述量が多い
    • 開発スピードが遅い
  • メリット
    • データ型に関するエラーはプログラムを実行しないと分からない
    • 実行速度が遅い

言語

利用ケース(個人的な意見)

静的型付け言語が向いているケース

  • 大規模・大人数
  • スケールする可能性が高いサービス(自社サービス)
  • 安全性・パフォーマンス重視(金融・ゲーム)

動的型付け言語が向いているケース

  • 小規模・小人数
  • スケールする可能性が低いサービス(受託など)
  • 開発スピード重視(スタートアップ)

所感

最初に開発した言語がJavaだったり、今はC#を使っていることもあり静的型付け言語の方が贔屓目な書き方になってしまった。

ただ世間的にも最近JavaScript→TypeScript、Ruby→Goに移行している事例を割と見るので、型があるほうが安心して開発できると感じる。

参考

フロントエンドエンジニアのロードマップ(2021)読解

はじめに

結論から書くと、今後はフロントエンドに注力していこうと思います。

現状フロントエンド・バックエンド両方担当していますが、下記理由からフロントエンドに注力しロードマップを参考に学んでいこうと思います。

なぜフロントエンド?

会社で受講したWebのセキュリティ研修がきっかけです。
IPAのAppGoatとFlatt SecurityのKENROを受講しましたが、似たような内容でもKENROの方が使いやすかったです。(IPAさんごめんなさい)

どうして使いやすかったのかはうまく説明できませんが、色を使いすぎていない、スペースが適度に空いているなどデザインの面が良かったからだとは考えています。

もともとユーザーも自分も使いやすいと思えるサービスを開発したいと考えていましたが、「使いやすい」の定義が曖昧でした。

ただ2つのサービスを使ってみた経験から、使いやすさは目に見える画面に影響されることが多いと考えたため、目に見える部分を担当するフロントエンドを専門にしたいと思うようになりました。(レスポンスが遅い、すぐエラーになるなど正常に動作することはクリアしている前提の話ですが)

デザイナーでもよくない?

画面を担当するのであればデザイナーでもよくないかと思いましたが、過去にデザイン系の案件を担当してデザインを考えているときよりもコードを考えてたり、書くことの方が好きなためエンジニアとして働きたいと思っています。

過去に担当した案件から、デザインは客観的に説明することが難しい(主観的になってしまう)ことが多いイメージです。色のコントラスト比や黄金比など数値にできるものならまだしも、レイアウトやUIの使いやすさは個人の感覚に左右されることが多く、自分が納得してデザインを決めることができませんでした。(私が知らないだけで、そういったものの理論ややり方もあるかもしれませんが)

デザインに対し、プログラムは客観的に説明できることが多く、自分も納得感を持って仕事ができていました。(同じ処理は繰り返し処理にしてコード量を減らす、複数箇所から参照される値は変数・定数にして改修時に直す箇所を少なくするなど)

なぜロードマップ?

フロントエンドを専門にしていくにあたり、何を学べがいいか分からないため、全体像を知ることができるものを探していました。

今回参考にするのはroadmap.shのFrontendDeveloperのロードマップです。Zennなど技術系サイトに掲載されたり、テック系のYouTuberが紹介していました。

何を学ぶ必要があるかを知るためにロードマップを読解し、その中から今後学んでいく領域について書いていこうと思います。

ロードマップ

FrontendDeveloper roadmap

画像の中心の1本の線でつながっているブロックごとにどういった内容か書いていきます。

マークの意味

画像左上のマークの意味です、上にあるものほどおすすめな選択肢になっています。

  1. Personal Recommendation / Opinion
    おすすめな選択肢

  2. Alternative Option - Pick this or purple
    代わりの選択肢、選ぶならこれか上記のもの

  3. Order in roadmap not strict(Learn anytime)
    いつでも学んでいい、順番は守らなくていいもの

  4. I wouldn't recommend
    非推奨、やらなくてもいい

項目

項目内のトピックについて箇条書きしていきます。太字は優先度が高い選択肢です。(マークの意味の上から2項目の選択肢)

Internet

インターネット、HTTP、ブラウザなどそもそもの基礎となる技術。
フロントエンドはパフォーマンス向上のために特にブラウザの知識は持っておく必要がありそう。

  • How does the internet work?
  • What is HTTP?
  • Browers and they work?
  • DNS and how it works?
  • What is Domain Name?
  • What is hosting?

HTML

HTMLの基礎、フォーム・バリデーション、ベストプラクティス 。
基本的には書けるけど、何が良い書き方なのかは知っておいた方がよさそう。

  • Learn the basics
  • Writing Semantic HTML
  • Forms and Validations
  • Conventions and Best Practices

Semanctic HTMLは要素に目的・役割を持たせること。検索エンジンがページの検索のランキングを上げる、目の不自由なユーザー向けの読み上げソフトのページ移動を補助するなどの利点がある。

CSS

CSSの基礎、FloatsやFlexなどのレイアウト、端末ごとによって表示が異なるレスポンシブデザイン。

  • Accesibility
  • SEO Basics
  • Learn th basics
  • Making Layouts
  • Responsive design and Media Queries

Accesibilityはフォントサイズを上げる、行間を空けるなど、ユーザーがより快適になるようにデザインすること。

SEO検索エンジンで自社のページが検索時に上位表示されるように最適化する戦略。toC向けのサービスはこの知識も求められそう。(toB向けサービスでも広告記事は同様に必要かも?)

JavaScript

JavaScript基礎、DOM操作、非同期通信、ES6・JavaScriptモジュール、バブリングやスコープなど概念。

  • Syntax and Basic Constructs
  • Learn DOM Manipulation
  • Learn Fetch API / Ajax(XHR)
  • ES6 + and modular JavaScript
  • Understand the concepts Hosting, Event Bubbling, Scope, Prototype, Shadow DOM, strict

普段ES5で書いているので、ES6は改めて学ぶ必要がありそう。バブリングやスコープなどJavaScript固有の概念も理解しておく。

Version Control Systems

バージョン管理システム、Gitの基本操作。

  • Basic Usage of Git

Repo hosting services

GitのWebサービスにあたるもの。GitHubを覚えればOK。(BitBucketを使ったことあるけど、UIが違うだけでほぼ同じだったので、GitHubだけでよさそう)

Web Security Knowlwdge

最低限覚えておくセキュリティの知識。

  • HTTPS
  • Contents Security Policy
  • CORS
  • OWASP Security Risks

Package Manager

主にJavaScriptで開発されたモジュールを管理するためのシステム。
手動でそれらモジュールの設定ファイルや更新を行うのは手間が掛かるため、簡単なコマンド入力でそれらの作業ができるようになる。
- npm - yarn

CSS Architecture

  • BEM
  • OOCSS
  • SMACSS

モダンなフレームワークCSS-in-JSがある場合は、CSS設計は優先度は低い。
ただBEMには精通していることは推奨。

CSS Preprocessors

  • Sass
  • PostCSS
  • Less

CSS設計と同じくフレームワークCSS-in-JSが主流になっているので、こちらも優先度は低い。
ただ余力があれば知識を付けておくとよい。

Build Tools

Task Runner

ファイルの更新を監視しコンパイルするなどのタスクを自動化してくれるツール。

  • npm scripts
  • Gulp

Linters and Formatters

  • Prettier
  • ESLint
  • StandardJS

静的解析ツール、コードを整形してくれたり、策定したルールに沿っていない箇所を教えてくれたりするもの。

Module Bundlers

  • Webpack
  • Rollup
  • Parcel

複数のファイル(モジュール)を1つの最適化されたファイルにバンドル(まとめる)するツール。

Pick a Framework

フロントエンド開発のフレームワークと状態管理ライブラリ

  • React.js
    • Reduc
    • MobX
  • Angular
    • RxJS
    • NgRx
  • Vue.js
    • Vux

Modern CSS

CSS in JSと呼ばれるJavaScript内にスタイルを記述することで、スタイルをコンポーネント単位に指定する技術

  • Styled Components
  • CSS Modules
  • Styled JSX
  • Emotion
  • Radium
  • Glamorous

Web Components

再利用なカスタム要素で、他のコードから独立してカプセル化する機能を持つ

  • HTML Templates
  • Custom Elements
  • Shadow DOM

CSS Frameworks

JS based

JavaScriptフレームワークと共に利用することが推奨とされているもの

  • Reactstrap
  • Material UI
  • Tailwind CSS
  • Chakra UI

CSS first

デフォルトでJavaScriptコンポーネントが付属していないCSSファーストなもの

  • Bootstrap
  • Materialize CSS
  • Bulma

Testing your Apps

単体、結合、機能テストの違いとツールを使ってそれらを作成する方法を学ぶ

  • Jest
  • react-testing-library
  • Cypress
  • Enzyme

Type Checkers

静的型チェッカー、実行前に型が正しく定義されているか検証する

  • TypeScript
  • Flow

Progressive Web Apps

先進的なWebアプリで使われる様々なWebAPIを学ぶ。

  • Storage
  • Web Sockets
  • Service Workers
  • Location
  • Notifications
  • Device Orientation
  • Payments
  • Credentials

パフォーマンスの計算、測定、改善をする

  • PRPL Pattern
  • RAIL Model
  • Performance Metrics
  • Using Lighthouse
  • Using Dev Tools

Server Side Rendering(SSR)

サーバーサイドでレンダリング(HTMLを生成)し、ブラウザはレンダリングされたファイルを表示する。Node.jsの実行サーバーが必要、サーバー側の負荷が増加するが、SPAよりも表示速度が速い。

  • React.js
    • Next.js
    • After.js
  • Angular
    • Universal
  • Vue.js
    • Nust.js

GraphQL

API向けに作られたクエリ言語及びランタイム。クライアントが必要なデータ構造を定義することで、サーバーから必要以上のデータを返されることを防止でき効率がよいとされる。

Static Site Generators

静的サイトジェネレータ、WebサイトのHTMLファイルを生成するツール。
CMSと異なり、すべてのHTMLファイルを作成するため、レスポンスが速い・サーバー代が掛からないなどのメリットがある。

  • Next.js
  • GatsbyJS
  • Nuxt.js
  • Vuepress
  • Jekyll
  • Hugo

Mobile Application

モバイルアプリ、iOSAndroid両方を開発できるクロスプラットフォームフレームワークが推奨。

  • React Native
  • NativeScript
  • Flutter
  • Ionic

Desktop Applications

VSCodeやslackなどPCにインストールして利用するアプリ

  • Electron
  • Carlo
  • Proton Native

Web Assembly

ブラウザ上で動作するバイナリコード。JavaScriptより高速で主要ブラウザでは対応している。2019年にW3C(Webの標準化団体)は公式水準として受け入れている。

これから学ぶ領域

まずはTypeScriptとSPAを勉強しようと思います。上記2点が、現在フロントエンドエンジニアでの必須要件になっている求人が多いためです。

このこと自体は初めから求人だけ見れば良かったかもしれません。 ただロードマップを読解したことで何を学ぶべきかの全体像を把握することができました。ロードマップを参考に今自分が勉強している場所を確認しながら、今後も学習を進めていきたいと思います。

参考

【C#/NUnit/Moq】単体テストについて

背景

業務で利用しているNUnit・Moqを学習するにあたり、そもそも単体テストについての知識がないので単体テストの目的、手法、ライブラリの使い方などついて自分用にまとめます。

なお、単体テストは自動化されたテストを前提に記載しています。分類としての単体テストでは自動テストを必ずしも意味していないため。(手動の単体テストはマイナーだと思いますが)

単体テスト

比較的小さなプログラムのテスト。テスト対象は主にクラスやメソッドなどテスト可能な最小単位な部品(ユニット)。

メリット

  • バグの早期発見
    単体テストはコードの開発直後にテストするため、バグがあった場合にすぐに発見できる。
    またテスト対象の粒度が小さいため、問題があった箇所を特定しやすい。

  • 品質の維持
    リファクタリングや影響箇所の修正などで既存コードを改修した際に、テストコードがあれば改修による問題を発見・修正しやすくなるため品質を維持しやすい。

デメリット

  • 開発者の工数増加
    単体テストはテストコードだけではなく、テストコードを呼び出すドライバやテストコードから呼び出されるスタブなどの準備が必要となる。
    開発者は稼働するコード以外にも開発する必要があるため、開発工数が増加してしまう。

  • 後回しにされやすい
    開発者の負担増加によるスケジュールの関係で、網羅的ではなく簡易的なテストだけで済まされてしまう場合がある。またテストコードのメンテナンス漏れやテスト実行されなくなってしまう可能性もある。

他のテスト

単体テスト以外にも以下のテストがある。

  • 結合テスト
    単体テストの次に行うテストで複数のプログラムを組み合わせて正常に動作するか確認するテスト。
    部品ごとの動作を確認する単体テストは完了しているため、主にデータの受け渡しや流れを確認する。

  • システムテスト
    結合テストの次に行うテストで、ユーザーが使用する環境を想定して確認するテスト。
    1つの機能を確認する結合テストは完了しているため、外部のシステムや他の機能に影響がないかシステム全体を確認する。

単体テストの手法

ホワイトボックステスト

プログラムの内部構造(関数や条件分岐など)に関するテストで、テスト対象のソースコードが正常に動作するか確認するテスト。

網羅手法

  • 命令網羅
    全ての処理を最低1回でも通す。

  • 分岐網羅
    全ての分岐の処理を通す。(分岐先に注目したテスト)

  • 条件網羅
    全ての分岐条件の真/偽条件の場合の処理を通す。(分岐条件に注目したテスト)

ブラックボックステスト

プログラムの内部構造は意識せず、入力に対して期待される結果が仕様通りか確認するテスト。

分割法

  • 同値分割法
    有効な値、無効な値を入力して想定となる結果になるか。

  • 境界値分割法
    有効な値と無効な値の境界となる値を入力して想定となる結果になるか。

NUnit/Moq

NUnit

C#Visual Basicなど.NET言語の単体テストフレームワークJava単体テストフレームワークであるJUnitから派生して開発された。

Moq

.NETのための唯一のモックライブラリ、予め作成しておいたインターフェースに対して、テストする際の振る舞いを設定することができる。

以下Microsoftチュートリアルや業務でよく見かけるキーワードについて記載。

属性

テスト用のクラスやメソッドなどに付与する属性

  • Test
    TestFixtureクラス内のメソッドをテストとしてマーキングする。パラメーターを利用しない単純なテストに使われることが多い。

  • TestFixture
    テストとオプションでsetup, teardownメソッドを含むクラスをマーキングする。

  • Setup
    TestFixtureの内側で使われ、各Testメソッドの前に実行される共通処理を書くことが出来る。

  • TearDown
    TestFixtureの内側で使われ、各Testメソッドの後に実行される共通処理を書くことが出来る。

  • Ignore
    何らかの理由でテストを実行すべきではないときに、TestFixtureTestの属性に加えることで、付与したテストを無視できる。

  • TestCase
    テストメソッドにパラメータを渡し、渡したデータでテストが実行される。

アサーション

テスト結果を判定するための機能、テスト結果によって成功・失敗と判定される。

  • Assert.AreEqual
    2つの引数が同一か判定する

  • Assert.NotEqual
    2つの値が異なるか判定する

  • Assert.Throws
    特定の例外がthrowされることを確認する

  • Assert.DoesNotThrow
    特定の例外がthrowされないことを確認する

  • Assert.Fail
    失敗を生成する、またプロジェクトに合わせて失敗時のメッセージやパラメーターを設定できる。

モック

データベースアクセスやネットワーク通信など外部通信が行われるテストにおいて、テスト用の結果を返す代わりのオブジェクト。

注意点
事前にテストするクラス・メソッドのインターフェースを定義する必要がある。また本物のクラスもそのインターフェースを実装する。

  • Setup
    特定のメソッドが呼ばれた際の戻り値や例外などの指定ができる。 このメソッドでテスト時のオブジェクトの振る舞いを決定する。

検証用アプリ

参考

【JavaScript】call・apply

  • 関数のthisを置き換える
    call・apply共に関数を呼び出し、呼び出した関数のthisを第1引数に指定したオブジェクトに置き換える。
var func  = function(){
    console.log(this);
}

func();
func.call({hoge: 1});
func.apply({hoge: 2});
//出力
//func()はwindowオブジェクトが出力される(長すぎるため省略)
{
  hoge: 1
}
{
  hoge: 2
}

違い

  • 第2引数の値
    callは第2引数以降に値を複数受け取る。applyは第2引数に1つの配列を受け取る。
var func  = function(a1, a2){
    console.log(this);
    console.log(a1);
    console.log(a2);
}

func.call({hoge: 1}, "c1", "c2");
func.apply({hoge: 2}, ["a1", "a2"]);
//出力
{
  hoge: 1
}
"c1"
"c2"
{
  hoge: 2
}
"a1"
"a2"

使用例

  • なりすまし
    callやapplyを利用すると本来は利用できない機能が、利用可能なオブジェクトになりすまして利用できるようになる。
<ul>
  <li>1</li>
  <li>2</li>
  <li>3</li>
  <li>4</li>
  <li>5</li>
  <li>6</li>
  <li>7</li>
  <li>8</li>
  <li>9</li>
  <li>10</li>
</ul>   
var liText1 = ( document.querySelectorAll( "li" ) ).map( function (e) {
    return e.textContent;
});
console.log(liText1)


var liText2 = Array.prototype.map.call( document.querySelectorAll( "li" ), function (e) {
  return e.textContent;
});
console.log(liText2)
//liText1 はmap()を持っていないため実行できずエラー
Uncaught TypeError: document.querySelectorAll(...).map is not a function

//liText2 はmap()を持っているArrayオブジェクトになりすますことで実行できる
["1", "2", "3", "4", "5", "6", "7", "8", "9", "10"]

参考

【C#】抽象クラス・インターフェース

前提

C#の抽象クラス・インターフェースの話

抽象クラス

  • 定義
    インスタンスを生成出来ないクラスで、継承して利用することを前提としたクラス
    ※継承...クラスの共通部分を別クラス(A)にまとめ、Aを継承することでAのプロパティ・メソッドを継承先で宣言することなく利用できる仕組み

  • ポイント

    • クラスやメソッドの前にabstractキーワードを付ける
    • 抽象クラスの中の抽象メソッドでは処理を書かず定義だけ行い、処理は継承先の具象クラスで書く必要がある
    • 継承できる抽象クラスは1つのみ(抽象クラスに限らず、具象クラスを継承する際も継承可能なクラスのは1つ)
  • 実装例

public class Test{
    public static void Main(){
        
        var normal = new NormalUser();
        var str1 = normal.GetUserClassName();
        
        var admin = new AdminUser();
        var str2 = admin.GetUserClassName();
        
        System.Console.WriteLine(str1);
        System.Console.WriteLine(str2);
    }
}

abstract class AbstractUser {//抽象クラス
   abstract public string GetUserClassName(); //抽象メソッド
}

class NormalUser : AbstractUser {//抽象クラスを継承
    public override string GetUserClassName(){//抽象メソッドをオーバーライド
        return "NormalUser";
    }
}

class AdminUser : AbstractUser {//抽象クラスを継承
    public override string GetUserClassName(){//抽象メソッドをオーバーライド
        return "AdminUser";
    }
}
//出力結果
NormalUser
AdminUser

インターフェース

  • 定義
    メソッドの実装を強制し、機能を追加するための仕組み

  • ポイント

    • classではなく、interefaceキーワードを付ける※アクセス修飾子はpublic固定
    • インターフェースを実装したクラスは、インターフェースの処理を実装しなければいけない(抽象メソッドと同じ)
    • 複数のインターフェースの継承が可能
  • 実装例
public class Test{
    public static void Main(){
        
        var user = new User();
        var str1 = user.GetId();
        
        var product = new Product();
        var str2 = product.GetId();
        
        System.Console.WriteLine(str1);
        System.Console.WriteLine(str2);
    }   
}
interface IGetId{//インターフェース
    int  GetId();
}

class User : IGetId {
    public int GetId(){//インターフェースのメソッドを実装
        var userId = 1;//本来はUserテーブルにidを取得しに行くが、ここでは仮に定義
        return userId;
    }
}

class Product : IGetId {//インターフェースのメソッドを実装
    public int GetId(){//インターフェースのメソッドを実装
        var productId = 2;//本来はProductテーブルにidを取得しに行くが、ここでは仮に定義
        return productId;
    }
}
//出力結果
1
2

抽象クラスとインターフェースの使い分け

調べていくうちに想像より複雑だったため、また別の記事として作成予定。

参考

プロセス・スレッド・並列処理

プロセスとスレッド

プロセスやスレッドやマルチスレッドや並列処理など関係ありそうだけど、今まであやふやなまま放置していたので、まとめる。

プロセス

OSが実行しているプログラム。
WordやExcelなどタスクマネージャーで表示されるもの。 プロセスが並行処理されることを「マルチプロセス」と呼ぶ。

スレッド

プログラムの実行単位。
CPUのコアは1コアあたり、1スレッドしか実行できない。そのため、スレッド=CPUコアの処理単位。
ex)画面を描画するスレッド、キー入力を受け取るスレッドなど。

スレッドはプロセスの中に含まれ、1つのプロセスの中で複数のスレッドを動作させることができる。(マルチスレッド)

マルチスレッドにすることでCPUの複数のコアに処理を割り振れるため、シングルスレッドよりも処理を高速化できる。(CPUが複数コアに限る)

プロセスとスレッドの違い

  • 同じメモリ領域を共有するかしないか
    プロセスはOSからメモリ領域を割り当てられるため、各プロセスがメモリを共有することはない。
    ex)メモ帳に書いた文字がWordに反映されない。

    スレッドは同じメモリ領域を共有するため、マルチスレッドの場合はメモリの管理をしないとバグが発生する可能性がある。

並列処理(マルチスレッドプログラミング)

複数のスレッドを同時に実行するプログラムを作成することをマルチスレッドプログラミングと呼ぶ。

ただし実際は並行に処理を行っているのではなく、人間には分からない程高速でスレッドの切り替えをして、同時に処理を行っているようにみえている。

using System;
using System.Threading;
using System.Threading.Tasks;
 
public class TaskSample
{
   public static void Main()
   {
 
   // 並行処理
      var task1 = Task.Run(() => ThreadMethod("A"));
      var task2 = Task.Run(() => ThreadMethod("B"));
      task1.Wait();
      task2.Wait();
   }
 
   static void ThreadMethod(String str)
   {
      for(var i =0; i < 100; i++){
          Console.Write(str);
      };
      
   }
}
//値が交互に出力される
BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
  • スレッドセーフ
    複数のスレッドで同じリソースにアクセスしようとすると、想定の値にならないバグが発生する可能性がある。

    このバグを防止することをスレッドセーフと呼ぶ。 リソースを読み取り専用にする、排他制御(スレッドによる書き込み中は他のスレッドからのアクセスを不可にする)をかけるなど

参考

【Sass】@extendと@mixinの使い分け

定義したスタイルを複数のクラスで使用できるSassの@extendと@mixinの違いが分からなかったので、両者を比較して使い分けるべきケースをまとめる。

@extendの特徴

定義したスタイルを他のクラスに継承して使用できる

/* Sass */
.btn-base{
  border:1px solid;
  border-radius: 0.5rem;
  padding: 0.5rem;
}
.btn-success{
  @extend .btn-base;
  background-color: green;
}
.btn-error{
  @extend .btn-base;
  background-color: red;
}
/* CSS */
.btn-base, .btn-error, .btn-success {
  border: 1px solid;
  border-radius: 0.5rem;
  padding: 0.5rem;
}

.btn-success {
  background-color: green;
}

.btn-error {
  background-color: red;
}

プレースホルダーを使用する場合

継承元になったクラス(.btn-base)を利用しない場合は、プレースホルダー(%)を使用することでCSSコンパイルされない

/* Sass */
%btn-base{
  border:1px solid;
  border-radius: 0.5rem;
  padding: 0.5rem;
}
.btn-success{
  @extend %btn-base;
  background-color: green;
}
.btn-error{
  @extend %btn-base;
  background-color: red;
}
/* CSS */
.btn-error, .btn-success {
  border: 1px solid;
  border-radius: 0.5rem;
  padding: 0.5rem;
}

.btn-success {
  background-color: green;
}

.btn-error {
  background-color: red;
}

@mixinの特徴

定義したスタイルを他のクラスで呼び出して使用できる

/* Sass */
@mixin btn-base{
  border:1px solid;
  border-radius: 0.5rem;
  padding: 0.5rem;
}
.btn-success{
  @include btn-base;
  background-color: green;
}
.btn-error{
  @include btn-base;
  background-color: red;
}
/* CSS */
.btn-success {
  border: 1px solid;
  border-radius: 0.5rem;
  padding: 0.5rem;
  background-color: green;
}

.btn-error {
  border: 1px solid;
  border-radius: 0.5rem;
  padding: 0.5rem;
  background-color: red;
}

引数を使用する場合

@includeに引数を渡すことで、呼び出し元のクラスごとにスタイルを調整することが出来る

/* Sass */
@mixin btn-base($bgc:transparent){
  border:1px solid;
  border-radius: 0.5rem;
  padding: 0.5rem;
  background-color: $bgc;
}
.btn-success{
  @include btn-base(green);
}
.btn-error{
  @include btn-base(red);
}
/* CSS */
.btn-success {
  border: 1px solid;
  border-radius: 0.5rem;
  padding: 0.5rem;
  background-color: green;
}

.btn-error {
  border: 1px solid;
  border-radius: 0.5rem;
  padding: 0.5rem;
  background-color: red;
}

比較

@extend

  • メリット

    • コード量が少ない
      継承元と継承先のクラスが1セレクタにグルーピングされるため、共通スタイルのコードの重複を防止できる
  • デメリット

    • 引数が使用できない
      @mixinと違い引数が使えない分、継承されるスタイルは固定になる

    • 可読性が下がる
      継承元と継承先のコードが離れるため、コードの可読性が落ちる。
      そのため、グルーピングできない関連性がないクラスへの@extendは控える。(関連性があるコードは距離が近く、関連性がないコードは距離が遠いため)

@mixin

  • メリット

    • 引数が使える
      @includeしたクラスごとにスタイルの調整が出来る

    • 可読性が高い
      コードが@includeしたクラスに全て記載されるため、可読性が高い

  • デメリット

    • コード量が増える
      @includeしたクラスに同じスタイルが記載されるため、コードが重複する。

まとめ

グルーピング出来るような関係性のあるスタイルは@extendを使用する
関係性がない、または引数を利用したいなら@mixinを使用する

まとめのまとめ

継承関係があるなら@extend、それ以外は@mixin

参考