じぶん Release Notes(ver 0.29.10)
先日、2021/2/28、atEaE (ver 0.29.10) がリリースされました👏
他の人たちに習って自分もリリースノートを作っていこうと思います。
versioningは『0.年齢.月齢』とします!
(引越し作業で疲れて、3/1に公開するのを忘れていました...)
📚Input
【読書】
読書中
読了
【技術関連】
- Golangの基礎的な部分で覚えの甘い部分(context、channel周り)を復習
- CSSの基礎を復習(セレクタやスタイル優先順位周り)
📝Output
【はてなブログ】
- 『CommandLineSelectableMenu』をリリースしました。
- Github Actionを活用してnugetへpackageの公開を行う。
- Github Actions で microsoft/setup-msbuild@v1.0.1が失敗する。
- EntityFramework Coreを使って動的にテーブルへ追加、削除を行う。
- CSSの :not疑似クラスの使い方
- 『CommandLineSelectableMenu』 v1.2.0 リリースノート
- コードリーディングが捗る"github1s.com"
- 画面のレスポンスタイム指標
- HTMLのタグの分類
- Swaggerを使った開発アプローチ
- Swashbuckleを使用して、凝らないSwaggerドキュメントを生成する。(ASP.NET WebAPI偏)
- WindowsでPython3系を実行するとMSストアが開く時の対処方法
【Qiita】
- Semantic Versioningでよくある間違いたち
Rewrite扱いですが、元々限定公開だったメモ書きを公開用に書き直しています。
【Github】
- CommandLineSelectableMenuのIssue消化とリリース
🚩KPT
【Keep】
- 毎日コーディングは何とか継続中(masterへのmerge待ち複数)
- 少ないながらも読書も継続できている。
【Problem】
- 在宅業務も1年近くになり、時間の使い方のメリハリがなくなっている。
- 引越しと各種手続きに時間を割かれすぎて、Inputが少なくなってしまった。
- Outputが棚卸し的な内容ばかりになっている。
【Try】
- GithubへのOutputを継続する。
- タイムスケジュールを立てて行動してみる。
🎯リリース概要
振り返ると、2月は非常に忙しい月でした。
まず、転職にあたり日常業務をしながら、引継ぎ資料の作成をしていました。
これだけでも十分にキツイのですが、加えてプライベートでは引越しも控えていたため、荷物の整理と部屋の整理に追われる日々。
加えて、新しい家族(猫)が増えるということで、空いた時間はひたすら猫グッズの検索。
更にさらに個人開発もしたいし、ブログも書かねばということで我ながら2月は少し詰め込み過ぎました。
3月はもう少し、落ち着いてInput,Outputできるようにしたいと思います。
WindowsでPython3系を実行するとMSストアが開く時の対処方法
はじめに
pythonをインストール後、インタプリンタを起動しようするとインタプリンタが起動せず、Microsoft Storeが代わりに起動してしまう。という事象があったので、備忘録として残しておきます。
確認環境
今回の事象が確認できたのは、以下の環境です。
- Windows 10 Pro
- Python 3.9.2
VSCodeもしくは、Powershellから直接python
コマンドを入力すると、Microsoft Storeが起動してしまいます。
python
コマンドを入力しても、インタプリンタは起動しません。代わりにMicrosoft Storeが起動してしまいます。
対処方法
① パスの順番を入れ替える
方法としては、タイトル通りなのですが、それだけだとあまりにも味気ないので、そこに至る過程についてもざっくりと説明します。
まずは、『python
コマンドを実行して、Microsoft Storeが起動する。』という事象が確認されているので、実行されているコマンドがインストールフォルダ配下の.exeファイルなのかを確認します。
PowershellではGet-Command
(エイリアスはgcm
)を使用して、コマンドのパスを調べることができます。
より詳細な情報が知りたい場合は、Format-List
コマンド(エイリアスはfl
)を使いましょう。
%USERPROFILE%\AppData\Local\Programs\Python\Python[version]
が本来のインストールフォルダになりますが、%USERPROFILE%\AppD[f:id:EaE:20210226222902p:plain]ata\Local\Microsoft\WindowsApps
というフォルダの異なるpython.exe
ファイルが呼び出されていることが分かりました。
次に環境PATH設定の解決順序を確認します。
↑の通り、Programs\Python
よりもMicrosoft\WindowsApps
の方が解決順序が上に設定されています。この解決順序を変更していきます。
修正後の環境PATHが↑の通りです。先ほど、Microsoft\WindowsApps
より下に設定されていたPythonフォルダへのパス情報をすべて、Microsoft\WindowsApps
より上に設定しています。
最後にpython
コマンドのパスを確認して終了です。
さいごに
- 環境PATHの解決優先順位を変更する。
これ以外にも解決方法があれば、教えてもらえると助かります。
Swashbuckleを使用して、凝らないSwaggerドキュメントを生成する。(ASP.NET WebAPI偏)
はじめに
ASP.NET WebAPI(.NET Framework)とSwashbuckleをして、コードファーストアプローチからSwaggerドキュメントを生成します。
『何故に今更、ASP.NET WebAPIを使うの?ASP.NET Coreじゃダメなの?』と思った方もいらっしゃるかと思いますが、業務では.NET Frameworkを使う機会がいまだに多いという個人的な事情です...
個人開発であれば、ASP.NET Core一択です。
まずはコードを見せろ。という方はこちらをどうぞ。
開発環境
- Visual Studio 2019
- .NET Framework 4.7.2
- C# 7
- ASP.NET WebAPI
- Swashbuckle5.6.0
Swashbuckleのインストール
Swashbuckleは.NET用に提供されているSwaggerコードファーストアプローチ用のライブラリです。 今回は、ASP.NET WebAPIで作成していますが、もちろんASP.NET Coreにも対応しています。
PackageManagerから『Swashbuckle』をインストールしてください。
Install-Package Swashbuckle
凝らないドキュメントの生成
今回は、コードファースト(ボトムアップ型)のアプローチでSwaggerドキュメントを生成していくので、APIのコードが必要となりますが、そこについてはプロジェクトによって十人十色なため割愛します。以降に紹介するコードは、サンプルとして公開しているので、そちらを参考にしてください。
Swashbuckleをプロジェクトに追加すると、App_Start
ディレクトリの中にSwaggerConfig
が作成されます。下記のようなファイルが追加されているかと思います。(実際に生成されるファイルには大量にコメントがされているはずなので、簡略化しています。)
[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")] namespace WebAPIExample { /// <summary> /// Swagger Configuration. /// </summary> public class SwaggerConfig { /// <summary> /// Register swagger configuration. /// </summary> public static void Register() { var thisAssembly = typeof(SwaggerConfig).Assembly; GlobalConfiguration.Configuration .EnableSwagger(c => {}) .EnableSwaggerUi(c => {}); } } }
ここから特別な設定などは追加せず、凝らないドキュメントの生成とUIの設定を行っていきます。
【ドキュメントの生成】
まずはドキュメントの生成を行っていきます。
ドキュメント生成に関わっているのは, EnableSwagger(c => {})
の部分で、この中に設定を追加していきます。実際のAPIに関する基本情報を追記したのが下記になります。
[assembly: PreApplicationStartMethod(typeof(SwaggerConfig), "Register")] namespace WebAPIExample { /// <summary> /// Swagger Configuration. /// </summary> public class SwaggerConfig { /// <summary> /// Register swagger configuration. /// </summary> public static void Register() { var thisAssembly = typeof(SwaggerConfig).Assembly; GlobalConfiguration.Configuration .EnableSwagger("docs/{apiVersion}/swagger", c => { // api infomation. c.SingleApiVersion("v1", "WebAPIExample") .Description("This repository is example of ASP.NET WebAPI (.NET Framework) with Swashbuckle.") .License(l => { l.Name("MIT") .Url("https://github.com/atEaE-samples/aspnet-webapi-swashbuckle-example/blob/master/LICENSE"); }) .TermsOfService("There are no restrictions on use.") .Contact(cb => { cb.Name("atEaE") .Email("sample@example.com") .Url("https://github.com/atEaE"); }); // use schemes c.Schemes(new[] { "http", "https" }); }) .EnableSwaggerUi(c => {}); } } }
EnableSwagger()
の第一引数に指定している"docs/{apiVersion}/swagger"
文字列は、Swaggerドキュメントのエンドポイントを表しています。{apiVersion}
の部分は、後述するAPIVersionが自動的にパスに反映されます。
今回のAPIはシングルAPIなので、c.SingleApiVersion()
を使用して、ドキュメントを生成しています。
第一引数に"v1"
APIのVersionを、第二引数にWebAPIExample
APIのタイトルを設定します。
SingleApiVersion()
メソッドは、Swaggerドキュメントのinfo
に相当するInfoBuilder
を返却するため、メソッドチェーンさせることで設定情報を記述することができます。
InfoBuilder
で設定可能な項目は下記の通りです。
Description()
: ドキュメントについての説明License()
: APIのライセンスTermsOfService()
: 利用規約Contact()
: APIについての問い合わせ先
Contact()
, License()
はそれぞれ、Actionを引数として受け取るため、さらに詳細なプロパティを設定することができます。
c.Schemes()
には、APIの通信プロトコルを設定しています。この例では、https
, http
の2つを設定しています。
【SwaggerUIの有効化】
何となく気づいている方もいると思いますが、SwaggerUIの有効化はすでに完了しています。
EnableSwaggerUi(c =>{});
が設定されているため、SwaggerUIが有効となっています。
ここまでで、ドキュメント生成に関する準備は終了です。
Swaggerドキュメントの確認
最後にSwaggerドキュメントを確認していきます。 サンプルAPIをDebug起動させると、下記のようなIndexページに遷移するかと思います。
Indexページに遷移したら、https://localhost:44377/swagger
もしくは https://localhost:44377/swagger/ui/index
に遷移することで、SwaggerUIのインデックスページを確認することができます。
メソッドに応じたパス情報、返却されるモデル情報についても確認することができます。
UIの元になっているSwaggerドキュメントは、先ほど設定したパスにアクセスすることで確認できます。
(パステンプレートに、"docs/{apiVersion}/swagger"
を。Versionにv1
を設定しているので、https://localhost:44377/docs/v1/swagger
にアクセスすることで、ドキュメントを確認することが出来ます。 )
{ "swagger": "2.0", "info": { "version": "v1", "title": "WebAPIExample", "description": "This repository is example of ASP.NET WebAPI (.NET Framework) with Swashbuckle.", "termsOfService": "There are no restrictions on use.", "contact": { "name": "atEaE", "url": "https://github.com/atEaE", "email": "sample@example.com" }, "license": { "name": "MIT", "url": "https://github.com/atEaE-samples/aspnet-webapi-swashbuckle-example/blob/master/LICENSE" } }, "host": "localhost:44377", "schemes": [ "http", "https" ], "paths": { "/api/Users": { "get": { "tags": [ "Users" ], "operationId": "Users_Get", "consumes": [], "produces": [ "application/json", "text/json", "application/xml", "text/xml" ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/UserResponse" } } } }, "post": { "tags": [ "Users" ], "operationId": "Users_Post", "consumes": [ "application/json", "text/json", "application/xml", "text/xml", "application/x-www-form-urlencoded" ], "produces": [], "parameters": [ { "name": "value", "in": "body", "required": true, "schema": { "$ref": "#/definitions/UserRequest" } } ], "responses": { "204": { "description": "No Content" } } } }, "/api/Users/{id}": { "get": { "tags": [ "Users" ], "operationId": "Users_Get", "consumes": [], "produces": [ "application/json", "text/json", "application/xml", "text/xml" ], "parameters": [ { "name": "id", "in": "path", "required": true, "type": "integer", "format": "int32" } ], "responses": { "200": { "description": "OK", "schema": { "$ref": "#/definitions/UserResponse" } } } }, "put": { "tags": [ "Users" ], "operationId": "Users_Put", "consumes": [ "application/json", "text/json", "application/xml", "text/xml", "application/x-www-form-urlencoded" ], "produces": [], "parameters": [ { "name": "id", "in": "path", "required": true, "type": "integer", "format": "int32" }, { "name": "value", "in": "body", "required": true, "schema": { "$ref": "#/definitions/UserRequest" } } ], "responses": { "204": { "description": "No Content" } } }, "delete": { "tags": [ "Users" ], "operationId": "Users_Delete", "consumes": [], "produces": [], "parameters": [ { "name": "id", "in": "path", "required": true, "type": "integer", "format": "int32" } ], "responses": { "204": { "description": "No Content" } } } } }, "definitions": { "UserResponse": { "type": "object", "properties": { "users": { "type": "array", "items": { "$ref": "#/definitions/User" } } } }, "User": { "type": "object", "properties": { "familyName": { "type": "string" }, "firstName": { "type": "string" }, "userName": { "type": "string" }, "email": { "type": "string" }, "gender": { "type": "string" }, "age": { "format": "int32", "type": "integer" }, "bio": { "type": "string" } } }, "UserRequest": { "type": "object", "properties": {} } } }
さいごに
- シングルAPIでコードファーストアプローチ型のドキュメント生成をするのは簡単
- 凝ったことをしないのであれば、API情報の設定のみで残りは設定いらず。
参考・引用
Swaggerを使った開発アプローチ
はじめに
Swaggerを使ったAPI開発は、業務でも個人開発でもお世話になることが多いのですが、具体的な『開発手法』や『開発アプローチ』について考えたことがなかったので、調べてみました。
2つの開発手法
Swagger 公式Blogや、個人Blogの中には、開発手法に関して言及しているものがいくつか存在します。 それらの中では主に2つの開発手法が示されています。
Design First or Code First: What’s the Best Approach to API Development? より引用
- デザインファースト(トップダウン型)
- コードファースト(ボトムアップ型)
の2つが紹介されています。
これら2つのアプローチについて、『どういったものなのか?』『どういった場合に使用が勧められるのか?』ということを次の項から見ていきます。
デザインファースト(トップダウン型)
『OpenAPIの仕様(swagger.yamlなど)から、コードを生成する。』手法を指します。
与えられた要件から、コードの元となるSwaggerドキュメントの設計を行います。Swaggerドキュメントの設計が完了した時点で、それを元にコードを自動生成していくといった形をとります。
適用が勧められるケースとして、下記のようなケースが紹介されています。
①外部ユーザーに対して重要度の高いAPIを公開する場合
外部ユーザーに対して、重要度の高いAPIを公開する場合は、APIの仕様が非常に重要になります。外部ユーザーはAPIの内部構造を覗き見ることができないため、仕様に関するドキュメントが全てとなります。 特に境界面となるインタフェースプロパティ、パス、パラメータは非常に重要なため、予め明文化されたSwaggerドキュメントなどからコードを自動生成する方が、情報の一貫性を保つことができます。
②チーム間での開発コミュニケーションを重要視する場合
開発の分化が進んでいるチームでは、バックエンドとフロントエンドが分かれていることが、ほとんどだと思います。
この場合、1チームや1人の開発者がフロントエンドとバックエンドを一緒に作るわけではないため、APIに関する情報を各チームに対して共有しておく必要があります。
情報共有を『コードを見て判断してください。』や『Excelドキュメントを参照してください。』のようにフォーマットの定まっていない形式で行ってしまうと、情報共有にかかる時間を無駄に費やしてしまうことになります。
Swaggerドキュメントで既定のフォーマットを使用すれば、円滑な情報共有を促すことができます。
フロントエンドはSwaggerドキュメントからエンドポイントの情報や認証情報、型に関する情報を得ることができます。Swaggerドキュメントから簡易的なMockサーバーを生成することもできます。
バックエンドは、そのままAPIを自動生成し、内部の処理を実装するだけで済みます。
コードファースト(ボトムアップ型)
『コードから、OpenAPIの仕様を生成する。』手法を指します。 与えられた要件から、コーディングを開始して機能が完成したところで、コードからSwaggerドキュメントを自動生成していくといった形をとります。
適用が勧められるケースとして、下記のようなケースが紹介されています。
①素早く製品をリリースしたい場合
デザインファーストでは、インターフェースに関わる部分のコード生成を自動化することはできますが、重要な『処理』に関する部分のコードは自動生成できません。
DBからデータを取得する処理や、パラメータに対して何らかの操作を行う処理もすべて自前で記述する必要があります。
そのため、スピードが重視される場面において、ドキュメント生成をしてから、インターフェース部分のコードを自動生成して、インタフェースを崩さないように処理部分を実装する。というプロセスはあまり好ましくありません。
加えて、デザインファーストはあくまでドキュメントから自動生成されたコード群に過ぎないため、運用を考慮したフォルダ構成やアーキテクトになっているわけではありません。
CI/CDによる素早いリリースプロセスを実行していくためには、Toolによる自動化が欠かせませんが、運用を考慮しないフォルダ構成やアーキテクトでは、この自動化が非常に困難になります。
こういった場合は、コードファーストで先に開発を行い、コードからSwaggerドキュメントを自動生成してしまう方が良いとされています。
②PrivateなAPIを開発する場合
外部公開を目的としないAPIや、企業内部で限定的な利用しかしないAPIを作成する場合は、コードファースト型の開発が適しているとされています。 これは、公開APIの開発と比較して、内部限定のAPI開発はインタフェースの規約が緩いことが多いため、仕様に関するドキュメントの重要性がそこまで高くない。というのが理由のようです。
まとめ
- OpenAPIの仕様から、コードを生成する『デザインファースト(トップダウン型) 』
- コードから、OpenAPIの仕様を生成する『コードファースト(ボトムアップ型)』
- どちらが良いではなく、実際の開発に求められる要件に基づいて手法を選択する。
参考・引用
HTMLのタグの分類
はじめに
普段はサーバーサイドばかりで、一向にフロントエンドの知識が身についていないのでHTML、CSSを一から復習し直すことにしました。
ということで、HTML, CSSに関しては当分の間、基礎的なことばかりになると思います。
HTML5以前のタグ分類
HTML5以前は、『ブロック要素』『インライン要素』の2つにタグは分類されていました。
ブロック要素は、1つのまとまり(ブロック)として認識される要素のことで、ブラウザで表示される際には前後に改行が入ります。ブロック要素の中には、別のブロック要素やインライン要素を配置することができます。
<div class="outline"> <div class="inner"> <p><strong>Hello world!!</strong></p> </div> </div>
インライン要素は、ブロック要素の内容情報として使用される要素のことです。文章の一部(インライン)として扱われます。ブロック要素とは異なり、前後に改行は入りません。インライン要素の中には、文字や別のインライン要素を配置することはできますが、ブロック要素は配置することができません。
<code> <span>import System;</span> </code>
HTML5で新たに導入された考え方
HTML5では、上記で説明した『ブロック要素』『インライン要素』という分類が廃止になりました。
文書の構造をより明確に表現できるように類似した特性に応じてカテゴライズし直され、新たな分類に分けられています。
(MDNでは、これらをContents categories:コンテンツカテゴリと表現しています。)
『文書の構造をより明確に表現できるように』ということですが、具体例としてこのサイトの簡略図を元に、HTML5以前とHTML5での文書構造の違いを見ていきます。
(理解しやすいように簡略化しています。)
HTML5以前であれば、div
タグを使用してid
やclass
属性を使いながら、それぞれのブロックが『何を表しているのか』を表現していました。HTML5以前は、タグだけでは文書構造は分からないため、属性を使用することで開発者が明示的に役割を与える必要がありました。
加えて『役割を与える』といっても、統一された規格に基づいたものではありません。あくまで開発者が、id="header"
という属性を付けたから、そのサイトではヘッダとして扱われるというだけです。他のサイトでは、id="head"
かも知れませんし、class="header"
かも知れません。
HTML5では、タグそのものが意味をもっており、id
やclass
といった属性を使用せずに『何を表しているか』を表現できます。そのため、タグのみで文書構造の表現が完結していてかつ、統一された規格に則ったものになっています。header
タグを使えば、どのサイトであれその要素はヘッダーで、nav
タグを使えば、どのサイトであれその要素はナビになります。
仮にCSSがなかったとしても、HTMLだけで『どこが何を表しているのか』を統一された規格を元にアウトラインを知ることができます。
(div
ばかり使ってコーディングするな!と怒られた経験のある方もいるかも知れませんが、この考え方を無視してしまっているためだと思われます。)
カテゴリ分類
カテゴリは以下のように分類されます。
HTML Living Standard より引用
https://html.spec.whatwg.org/multipage/dom.html#kinds-of-content
(本家のサイトではSVGにより、アニメーション付きで各コンテンツを確認できます。)
- メタデータ・コンテンツ
- フロー・コンテンツ
- セクショニング・コンテンツ
- ヘッディング・コンテンツ
- フレージング・コンテンツ
- エンベディッド・コンテンツ
- インタラクティブ・コンテンツ
合計で7つのカテゴリに分類されます。
※ 図からも分かる通り、1つのタグが複数のカテゴリに含まれる場合もあります。
【メタデータ・コンテンツ】
名前の通り『メタデータ』を取り扱うコンテンツ分類になります。
メタデータ以外のコンテンツに対する『表示』『動作』といった設定はここに記載します。
base
, link
, meta
, noscript
, script
, style
, template
, title
などが該当します。
【フロー・コンテンツ】
body
タグの内部で本文要素として使用されるものがフローコンテンツとなります。ほぼすべての要素がここに該当します。↑の図からも分かるように、残りのコンテンツは、フロー・コンテンツがさらに細分化されるような形になります。
(一部のメタ要素もここに該当します。)
【セクショニング・コンテンツ】
特定の領域を区切る場合、まとまりを定義し、アウトラインを作成する場合に使用されるコンテンツが分類されます。
article
, aside
, nav
, section
【ヘッディング・コンテンツ】
見出しを表す要素がここに分類されます。
h1
, h2
, h3
, h4
, h5
, h6
, hgroup
【フレージング・コンテンツ】
文書テキストや、テキスト内の段落内のマークアップに使用されるタグなどが分類されます。
a
, abbr
, area
, audio
, b
, bdi
, bdo
, br
, button
, canvas
, cite
, code
, data
, datalist
, del
, dfn
, em
, embed
, i
, iframe
, img
, input
, ins
, kbd
, label
, link
, map
, mark
, math
, meta
, meter
, noscript
, object
, output
, picture
, progress
, q
, ruby
, s
, samp
, script
, select
, slot
, small
, span
, strong
, sub
, sup
, svg
, template
, text
, area
, time
, u
, var
, video
, wbr
【エンベディッド・コンテンツ】
文書構造内に別のリソースをインポートするものなど、埋め込みを行うタグがここに分類されます。
audio
, canvas
, embed
, iframe
, img
, math
, object
, picture
, svg
, video
【インタラクティブ・コンテンツ】
ユーザーに対して対話的なIFを提供するタグがこのコンテンツに分類されます。
a
, audio
, button
, details
, embed
, iframe
, img
, input
, label
, object
, select
, textarea
, video
まとめ
- HTML5からブロック要素・インライン要素はなくなりコンテンツカテゴリが導入された。
- 統一された規格に基づき、HTMLだけで文書構造のアウトラインを把握できるようになった。
参考・引用
- HTML Living Standard
- Content categories - HTML: HyperText Markup Language | MDN
- Inline elements - HTML: HyperText Markup Language | MDN
- [Block elements - HTML: HyperText Markup Language | MDN](https://developer.mozilla.org/en-
画面のレスポンスタイム指標
はじめに
- はじめに
- 画面レスポンス(応答性)の早さはどうして重要なのか?
- 応答時間の制限(3 response-time limits)
- 応答時間の制限(RAIL model)
- 2つの指標から見えること
- まとめ
- 参考・引用資料
パフォーマンスのテスト計画を作成するにあたり、画面のレスポンスタイムに関する指標を調べる機会があったので、そのまとめです。
画面レスポンス(応答性)の早さはどうして重要なのか?
まずはどうして、応答性の早さが求められるのかという点ついてです。
『Website Response Times』の中で、応答性について2つの観点から、その重要性を述べていました。
1. 人間の能力的観点
記憶力と注意力といった観点からみても、Webレスポンスが長くなることはあまり好ましくありません。
ワーキングメモリ自体は特定の期間、繰り返し思考されたりしない限り、長期記憶には残らないとされており、ワーキングメモリ内の情報の持続時間はおおよそ10~15秒とされています。そして、もちろん個人差があります。
そのため、10秒を超えるようなレスポンスは作業パフォーマンスの低下を引き起こすとされているそうです。
2. 人間の願望的観点
コンピューターを操作するとき、私たちはコンピューターに対して無意識のうちに従順であることを期待しています。検索の結果を気まぐれに返したり、クリックに反応する場合があったりなかったりすることはなく、私たちが操作した内容に対して、正確かつ迅速で、的確であることを期待しています。
なので、少しでも自分の期待に添わないような動き、例えば...
『クリックに反応しない。』
『検索結果のレスポンスにばらつきがある。』
といった場合には、『期待に背かれた』と感じてストレスを感じてしまいます。
応答時間の制限(3 response-time limits)
応答時間の基準に関しては、1993年の段階で3つの指標が出されています。
応答時間 0.1秒
ユーザーは、自身の操作に対して瞬時に反応しているような感覚を得ます。
リアルタイムの操作性が求められる機能に関しては、この秒数内に収めることがほぼ必須とされます。
応答時間 1秒
1秒程度の応答時間であれば、一瞬の遅延は感じることはあっても作業や思考自体が分断されるような感覚になることはありません。 この程度であれば、ユーザーはコントロール性をもってコンピューターを操作していると感じることができます。
応答時間 10秒
ユーザーの注意力が持続するのは1~10秒程度なので、ここが限界値です。
ユーザーから、ギリギリ許せるか...といったところです。明らかな遅延を感じ、コントロール性は失われているため、ユーザー体験としては決して良いものではありません。
応答時間の制限(RAIL model)
次にRAILモデルからみた、応答時間の制限についてです。
RAILモデルは、Google Web Fundamentalsで公開されている、『ユーザーファーストに基いて考えられた、ユーザーを中心に考えるパフォーマンスモデル』のことです。
このモデルは、以下の4つの要素から構成されています。
- Response(応答速度)
- Animation(動き)
- Idle(静止状態)
- Load(読み込み速度)
今回はあくまで、『画面のレスポンスタイム指標』がお題なので、Responseについてフォーカスします。
応答時間 0~16ミリ秒
ページ内動作であれは最高です。Good。
ただ、ユーザーはモーショントラッキングに長けているので、『アニメーション』ということであれば話は変わってきます。
ユーザーは毎秒60フレームがレンダリングされている限り、アニメーションに遅延を感じません。 逆にそれを超えるとユーザーは、アニメーションの遅延を認識し始めます。そのため、16ミリ秒という数値はアプリケーションのフレーム間隔でいえばギリギリということになります。
応答時間 0~100ミリ秒
この時間内であれば、ユーザーは即時に応答されていると感じます。これ以上長くなると、ユーザーは自分のアクションとリアクションの乖離を感じ始めます。
応答時間 100~300ミリ秒
ページ内の動作などであれば、ユーザーは遅延を感じ始めます。
応答時間 300~1000ミリ秒
ページの読み込みなど、ページ内動作以外であれば、スムーズな体験を提供しているというレベルです。 ページ内動作であれば、上記同様に遅延を感じ、アクションとリアクションの乖離を感じている状態です。
応答時間 1,000ミリ秒以上
1秒(1,000ミリ秒)を超えると、ユーザーは自身が実行したタスクへの関心を失い始めています。
応答時間 10,000ミリ秒以上
10秒(10,000ミリ秒)を超えると、ユーザーはイライラしてタスクをほぼ放棄している可能性が非常に高いです。ユーザーはもう戻ってこないかも知れません。
2つの指標から見えること
応答時間は場面とタスクに応じて
単純に『応答時間』だけをみて遅い云々の議論はできない。というのは非常に重要なことかなと思います。
上の指標だけでも、『アニメーション』『ページ内』『ページ読み込み』という3つが示されています。1秒はページ内では遅いかも知れませんが、画面の読み込み時間であれば快適な範囲内です。
20ミリ秒はページ内応答時間であれば十分高速ですが、『アニメーション』のフレームという観点では、60フレーム/秒に満たないため、若干の遅延を感じる可能性があります。
一言に画面の応答時間は『1秒』を基準にしましょう。のようなパフォーマンスの設定方法は、UXを損なう可能性があるため、『応答時間』だけを絶対の基準にするのは危険だなと感じました。
1秒あたりから違和感を感じ始める
『応答時間』を絶対の基準にするのは危険とは言いつつも、2つの指標を見る限り、1秒あたりでユーザーは何らかの違和感を感じ始めるようです。(もちろん場面やタスクによります。)
10秒を超えると作業なんてしていられない
そして、もう一つ重要な基準になるのは、10秒というラインです。
10秒を超えてしまえば、ユーザーの集中力は完全に切れて、イライラして作業どころではない。というのは2つの指標で共通しています。
(恐らくは私は10秒も待てません。6~7秒くらいでイライラしていると思います。)
まとめ
- 『応答時間』の秒数だけを絶対の基準にしてパフォーマンスを設定するのは危険。
- 『応答時間』とその時間がかかっている場面やタスクを合わせて考えるのが重要
- 『応答時間』だけに限って言えば、1秒でユーザーは違和感を感じ始める。
- 『応答時間』だけに限って言えば、10秒を超えればユーザーはいなくなる。
参考・引用資料
コードリーディングが捗る"github1s.com"
はじめに
今日はTLで流れてきた"github1s.com"が気になったので、調べてみたら意外と使い勝手が良かったのでまとめみました。
流れてきたTL
TLが流れたときは、正直最初は何がどうなっているのかよく分かりませんでしたが、じっくり見てみてるとなかなかすごい。
Github1s is really nice.
— Henning Dieterichs (@hediet_dev) 2021年2月9日
Just add "1s" after "github" when viewing code on https://t.co/0Wbx80muQp and VS Code loads up instantly: pic.twitter.com/rW5tdxrqIJ
リポジトリを開いたら、https://github1s.com/atEaE/hogehoge
のgithub
の後ろに1s
を追加するだけです。
たったそれだけで、ブラウザ上のVSCodeからソースコードを確認することができます。
github1s用のURL
https://github1s.com/atEaE/commandLineSelectableMenu
github1s自体はOSSで公開されています。
使用感
1. コードリーディングが捗る
今までOSSのソースコードを確認するときには、Github上だけではどうしてもコードが読みづらかったので、.zipをダウンロードしたり、cloneしたりしていました。
ところがgithub1s
では1s
を付け加えるだけで、Github上で見るよりも遥かにソースコードが読みやすいです。
開発者の方々ありがとう!
2. タグやブランチ別のソースコードも確認可能
タグ別のソースコードや、ブランチ別のソースコードも同じ要領で確認することができます。
タグ別はhttps://github.com/atEaE/hogehoge/tree/v1.0.0
、
ブランチ別はhttps://github.com/atEaE/hogehoge/tree/develop
のようになります。
後は同じように1s
を付けるだけで、ソースコードの確認ができます。
3. OAuth Tokenを登録すれば自身のPrivateリポジトリも確認可能
Githubの OAuth Tokenを使用していない場合は、Privateリポジトリのソースコードを確認することができません。
また、Github APIの使用上は1時間あたりのリクエスト数に限りがあります。
(未認証時は1時間あたり最大60リクエストまで可能。認証時は、1時間あたり最大5,000リクエストまで可能。)
Privateのリポジトリの確認がしたい場合や、リクエスト制限を緩和したい場合は、OAuth Tokenを登録しましょう。
Tokenは↑の通り、メニューから登録することができます。
VSCodeとの差異
1. フォルダ横断検索ができない
VSCodeと同じような見た目をしていますが、完全に同じ機能を有しているわけではありません。
まず、フォルダ横断した検索を実行することができません。
あくまで、アクティブファイルに対しての検索しかできません。
(アクティブファイルはEditor上で開いているファイルのことです。)
2. 一部の言語はコードジャンプが機能しない。
C#, golang, Typescript, javascriptでリポジトリを確認しましたが、C#, golangではコードジャンプが機能しませんでした。
Typescript, Javascriptに関しては、カーソルをHoverさせることで定義の確認まですることができました。
3. 基本的にファイルの編集はできない。
ファイルの編集は基本的にはできません。
『New File』から新規タブを開いた場合は、例外的に編集を行うことができますが、新規タブで作成したファイルは保存できないので、メモ書き程度なのかなと。思いました。
まとめ
- コードリーディングが捗る。
- 欲を言えば、フォルダの横断検索とコードジャンプが使えるといい。