javascriptで画像アップロード
mpaのdjnagoで画像をアップロードするにはフロントエンドではhtmlにinputタグ(type="file")をセットして、何らかのボタンを押してpostメソッドで送信し、views.pyにてrequest.POSTのような形で画像データを取り出してやれば画像の取り扱いはできた。
しかしながらSPAにおいてはjavascriptでいろいろ書いてやる必要があり、それの調査に時間がかかってしまったので記録に残しておく。
条件
- vuejsをもちいる。vueファイルにはinputタグを書かないで、ファイルアップロード等のボタンのみ表示されている状態で実装する。
概要
ポイントは4点あった。
- vueファイルに存在しないinputタグをどう対処するか?例えばvueファイルに直接書き込むか、tsファイルでDOM操作としてinputタグを作成するか。
- inputタグををクリックすると新たにウィンドウが表示されることを知っていたか。
- 新たに表示されたウィンドウに画像を選択した時どうやってそのデータを送信するか。
- 画像データ等はFormDataクラスを利用することを知っていたか。
2に関しては気づかなかったが、インプットタグをクリックするだけで画像選択するウィンドウが新たに生成される。3に関してはイベントリスナーに設置するのはcloseではなく"change"だと言うことに気づかなくてとても困った。
参考コード
myButton.vue
<template> <div> <button id="myButton">MyButton.vueのボタン</button> </div> </template> <script> import MyButton from './MyButton.ts' export default MyButton </script>
myButton.ts
import { Component, Vue} from 'vue-property-decorator'; import * as axios from 'axios'; // axios // https://www.digitalocean.com/community/tutorials/how-to-handle-file-uploads-in-vue-2 @Component({}) export default class MyButton extends Vue{ private mounted(): void{ const myButton = window.document.getElementById("myButton"); myButton?.addEventListener('click', this.openWindowButton); } private openWindowButton(): void{ console.log("Hello Vue From Button!!"); const inputImage = window.document.createElement('input'); inputImage.type = 'file'; inputImage.accept = "image/*"; inputImage.setAttribute("name", "file"); inputImage.multiple = true; //複数画像をアップロードしたい時にはコメントアウトを外して編集していく。。。 inputImage.addEventListener('change', this.uploadImage); inputImage.click(); } private async uploadImage(event: Event): Promise<void>{ const url = 'http://localhost:8000/myapp/image/' // Fileデータを送信する場合には、data = {'file': imageFile } みたいなことはできない // 必ずFormDataクラスを利用してデータを送信する。 const params = new FormData(); const imageFile = event.target.files[0]; params.append('file', imageFile); params.append('name', imageFile.name); const response = await axios.post(url, params); } }
typescriptとvueの単一ファイルコンポーネントを使う
設定条件:
- vue.js 2系(3系だと書き方が結構違うので困難だった。)
- typescriptを使う
- 単一ファイルコンポーネントを使う。単一ファイルコンポーネントではテンプレートとスタイルタグのみを記入し、スクリプトタグは.tsファイルの読込みのみ行う。
作ってみたファイル
1.単一ファイルコンポーネント MyButton.vue
~/Desktop/upload_images_by_js/frontend/src/components/MyButton.vueを作成。
このファイルが単一ファイルコンポーネントとなる。
なお、同ファイルscriptタグではtsファイルをインポートし、エクスポートする形を取るので、別途tsファイルを作成する。
<template> <div> <button id="myButton">MyButton.vueのボタン</button> </div> </template> <script> import MyButton from './MyButton.ts' export default MyButton </script>
2.単一ファイルコンポーネント MyButton.ts
~/Desktop/upload_images_by_js/frontend/src/components/MyButton.tsを作成。
import { Component, Vue} from 'vue-property-decorator'; @Component({}) export default class MyButton extends Vue{ private sss = 'sss'; }
このファイルは、typescriptチックに書くためにvue-property-decoratorのComponent, Vueを使っている。これを使うことでVueの定義をvueらしく書くのではなくtypescriptの様式で書くことができると認識している。 なお、ここでクラスを定義してエクスポートする。エクスポートされたクラスを単一ファイルコンポーネントであるMyButton.vueが受け取り、template, script, styleタグが揃った状態になる。
3.ページ機能を担うviews SampleComponent.vue
~/Desktop/upload_images_by_js/frontend/src/views/SampleComponent.vueを作成。 こちらもtemplate, script, styleを書く。このファイルはページを表示するためのものでvue routerで呼び出されるファイルである。したがって後でrouter/index.tsにてこのファイルとpathを紐付ける作業を行う。
<template> <div> <p>Sample Component</p> <my-button/> </div> </template> <script lang="ts"> import SampleComponent from './SampleComponent' export default SampleComponent </script>
4.ページ機能を担うviews SampleComponent.ts
~/Desktop/upload_images_by_js/frontend/src/views/SampleComponent.tsを作成。 SampleComponent.vueでインポートするためのファイルである。
import { Component, Vue } from 'vue-property-decorator'; import MyButton from '../components/MyButton.vue'; @Component({ components: {MyButton}}) export default class SampleComponent extends Vue { created(){ console.log('created');} mounted(){ console.log('mounted');} }
ここで注目したいのはSampleComponent.vueでmy-buttonタグを記述したが、ここでmy-buttonを使えるようにすることである。 そのためにComponentアノテーションでMyButton.tsをインポートして使う必要がある。
今回学んだのはここで、ページを表示するファイルのスクリプトタグ内でComponentを宣言しておけば単一ファイルコンポーネントを使えるようになる。また単一ファイルコンポーネントの名付け方があるのだろうけど、特にしない場合キャメルケースで作成したファイル名をケバブケースで記述するとhtmlで呼び出すことができるとも分かった。
5. パスとページファイルを紐付ける index.ts
~/Desktop/upload_images_by_js/frontend/src/router/index.tsを作成。
import Vue from 'vue' import VueRouter, { RouteConfig } from 'vue-router' import Home from '../views/Home.vue' import SampleComponent from '../views/SampleComponent.vue' Vue.use(VueRouter) const routes: Array<RouteConfig> = [ { path: '/', name: 'Home', component: Home }, { path: '/about', name: 'About', // route level code-splitting // this generates a separate chunk (about.[hash].js) for this route // which is lazy-loaded when the route is visited. component: () => import(/* webpackChunkName: "about" */ '../views/About.vue') }, // 以下を追加する { path: '/sample', name: "SampleComponent", component: SampleComponent } ] const router = new VueRouter({ mode: 'history', base: process.env.BASE_URL, routes }) export default router
6. 新たなページに飛ばすアンカータグを設置 App.vue
~/Desktop/upload_images_by_js/frontend/src/App.vue
<template> <div id="app"> <div id="nav"> <router-link to="/">Home</router-link> | <router-link to="/about">About</router-link> | <router-link to="/sample">Sample Component</router-link> | </div> <router-view/> </div> </template>
結果
作成したボタンコンポーネントをページで表示する事ができた。
↓↓↓↓↓↓↓↓↓↓↓↓
チームで開発する際に分かったこと
修正や機能追加について
-> どのように作業するのが効率が良いのか?
-> そもそも既存のコード全体を眺めて理解しようとしてもあまり理解できなかった
-> 修正や機能追加に関してはまず既存のプロダクトに似たような機能がないか確認する
-> 現状では、その確認の仕方はUIで似ているところを探し出す方法を用いる(フロントエンドしか通用しない可能性あり)
->探し出す方法=UIで似たような機能を見つけたらそのページのコンポーネントを特定する。特定方法はUIに存在または近くに存在する文字列をプロジェクトから検索する。この方法で参考にしたいコードがどのソースに含まれているか特定する。
-> そのソースを特定できたら、どこに参考にしたいメソッドやロジックがあるか特定する。その際、コードを眺めるだけでは理解が進まない。
-> だからリバースエンジニアリングのように既存のコードを消してみたり、コンソールに変数の値を出力して確認して理解する。
-> 理解できたら該当コードを参考にして修正、機能追加していく
で、この方法は既存のコードをごちゃごちゃいじってしまうからgitにそのいじった分を反映してしまうかもしれないと思ったけれども、gitで機能追加したものだけaddしていけば何のことはない事がわかった。
修正,機能追加の際に行う作業
作業中のコードが邪魔なら移動しておく
git stash -u
ブランチをきる
git checkout -b ブランチ名 # git branch ブランチ名 だとその後checkoutも必要になるから上のコマンドが望ましい
作業した分をプッシュ
git push origin HEAD # もしリモートリポジトリに対応するブランチが存在しない場合には新たにブランチが作成され、ブランチが既存にある場合はそのブランチに追加されていく
今の課題点
- どのポイントを読めば、それがどうなるかが分かっていない。目的をもてずにコードを眺める結果になってしまっている。
- visual studio codeで効率的なショートカットキーを覚えて作業すること
djangoとvuejsをcdn以外の方法で共存させる
npmにvueを入れて構築する方法を試みる。djangoはdjango rest frameworkを使う。
今回気になる事項は、
- どうやってdjangoとvueをcdn以外の方法で共存させる環境を構築するのか
- どういう仕組でdjangoとvueが連携する仕組みになっているのか
- vueを使うにあたり単一ファイルコンポーネント、VueルーターやVuexをどう使っていくかのサンプルがほしい
この辺をまとめられたら良いと思う。
参考資料
いつもお世話になっているNaritoさんのブログ
1 vuecliを入れる
naritoさんのブログを参考にしてvuecliを使って構築する方法を試みる。
vueとvuecliは別々に分けられているらしく、ドキュメントが独立しているようだ。
$ npm install -g @vue/cli
上記のコマンドでvue cliをインストールする。@vue/cliっていう表現で@が何を表すか気になったがこれは単純に@がついただけで意味はない。パッケージのネームとして@がつけられただけだという認識で良いと思う。
Warning regarding Previous Versions The package name changed from vue-cli to @vue/cli. If you have the previous vue-cli (1.x or 2.x) package installed globally, you need to uninstall it first with npm uninstall vue-cli -g or yarn global remove vue-cli.
2 vueプロジェクトを作成する
$ vue create frontend
プロジェクトを作成するとfrontendというディレクトリが生成される。このディレクトリにはnpmの設定関係のpackage.jsonやnode_modulesディレクトリ、vueのファイル関係を収めているsrcディレクトリが作られている。
プロジェクトを作ったときにはvuexとrouterをプロジェクトで使うように選択する。
3 App.vueを編集する
src以下にApp.vueがプロジェクトをvue作ると生成されている。これはどうやらsrc/main.jsが読み込まれ、このファイル内でApp.vueが読み込まれる。その流れでApp.vueが表示される流れになる。
App.vue
<template> <div id="app"> <Header/> <router-view/> <Footer/> </div> </template> <script> import Header from "./components/Header" import Footer from "./components/Footer" export default { name: 'app', components: {Header, Footer} } </script>
これで起動してみる。
npm run serve
4 単一ファイルコンポーネントを使う
cdnを使ったvueをdjangoで使う場合(MPAの場合)には、サーバーに各リクエストが送信され、返信されたファイルのscriptタグ内にVueを初期化するコードが埋め込まれている構造になっていた。
したがって、返信されるテンプレートには必ずVueの初期化が行われ、そのVue自身にmethodsやmountedを準備してやりvueを動かしていた。
今回のようなSPAの場合には、おそらくVueの初期化は一度限りでそのVueのライブラリを使ってページ遷移を実施する流れなのだと思われる。
5 vue routerをどうやって使うのか
必要な要素
- router/index.js内でVueにRouterを追加する(Vue.use(Router);)
- router/index.js内のRouter初期化のパラメータとしてroutesを追加する。このroutesがurl解決の役割を担う。
- 他のコンポーネントにrouter-link to="hoge"を書いてリンクできるようにセットする。
- router-viewタグに遷移先のページがレンダリングされるイメージなのでrouter-viewタグも忘れずにセットする。
routerに関して分かりやすい資料
https://b1tblog.com/2019/10/03/vue-router/
Vue Routerの書き方、使い方について解説 | ELOOP(イーループ) - 開発課題に取り組んで身につける実践型プログラミング学習サービス
routerに関するサンプルコード
GitHub - chiaki1990/vue_router_first_sample
疑問点
ランディングページでデータをデータベースから取得するにはどうするのか?
それはvueの
ライフサイクルを利用すれば良い。
mountedに非同期通信の関数を設置しておき、mounted時に非同期通信が開始されるように構成しておけば良い。
(環境構築手順とは別に)vue cliについて少し分かったことをメモ
a. vueがどんな風に動いているか
最初にsrc/main.jsを読み込む流れになると思われる。そのファイルの中で、
import { createApp } from 'vue' import App from './App.vue' import router from './router' import store from './store' createApp(App).use(store).use(router).mount('#app')
ここからApp.vueが読み込まれる。このApp.vueのファイルはtemplateタグを使っている。 templateタグ内では単一ファイルコンポーネントのタグを挿入したりしている。 そしてこの単一ファイルコンポーネントは同一ファイル内のscriptタグ内でimport して呼び出している。 このような流れで動いていると推測される。
<template> <div id="app"> <Header/> <router-view/> <Footer/> </div> </template> <script> import Header from "./components/Header" import Footer from "./components/Footer" export default { name: 'app', components: {Header, Footer} } </script> <style> </style>
b. vueとdjangoの組み合わせ方
主要なurlのルーティング機能はvueが担う。
vue routerが画面の内容を制御する。データベースからデータの取り出しはaxios等を使用して非同期処理でデータを取り出し、画面のデータとして反映する。
このデータの取り出しでdjangoのurls.pyを通じてdrfのapiviewを起動させ、データを取り出す仕組みとなっている。
typescriptのみで構築してみた
webpackやnpmの仕組みを分かっていないので一番シンプルな構成でtypescriptを実装する方法を試してみる。
参考資料
以下を記事に従って環境を構築してみた。プロジェクト名はsssとして作成してみた。
最新版TypeScript+webpack 5の環境構築まとめ(React, Vue.js, Three.jsのサンプル付き) - ICS MEDIA
1.下準備
macでnodebrewをインストールしてnode.jsをインストールする。 でnpmがあるbinのpathを通す。
そしてプロジェクトを作成する。
$ cd Desktop $ mkdir sss
2. package.jsonを生成する
以下のコマンドでpackage.jsonを生成する。
$ npm init
3. 必要なパッケージを追加
webpackとそのwebpack-cliの追加。
typescriptとts-loaderの追加。
$ npm install -D webpack webpack-cli typescript ts-loader
4. 各設定ファイルを作成、編集する
package.json、tsconfig.json、webpack.config.jsを扱う。
ファイル名 | 処理 |
---|---|
package.json | 編集 |
tsconfig.json | 新規作成 |
webpack.config.js | 新規作成 |
a. package.jsonの編集内容
{ "name": "sss", "version": "1.0.0", "description": "", "main": "index.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1", "build": "webpack", "watch": "webpack -w" }, "author": "", "license": "ISC", "devDependencies": { "ts-loader": "^8.0.7", "typescript": "^4.0.3", "webpack": "^5.2.0", "webpack-cli": "^4.1.0" }, "private": true }
b. tsconfig.jsonの編集内容
$ vi tsconfig.json
{ "compilerOptions": { "sourceMap": true, "target": "es5", // TSはECMAScript 5に変換 "module": "es2015", // TSのモジュールはES Modulesとして出力 } }
c. webpack.config.jsの編集内容
$ vi webpack.config.js
module.exports = { // モード値を production に設定すると最適化された状態で、 // development に設定するとソースマップ有効でJSファイルが出力される mode: 'development', // メインとなるJavaScriptファイル(エントリーポイント) entry: './src/main.ts', module: { rules: [ { // 拡張子 .ts の場合 test: /\.ts$/, // TypeScript をコンパイルする use: 'ts-loader', }, ], }, // import 文で .ts ファイルを解決するため // これを定義しないと import 文で拡張子を書く必要が生まれる。 // フロントエンドの開発では拡張子を省略することが多いので、 // 記載したほうがトラブルに巻き込まれにくい。 resolve: { // 拡張子を配列で指定 extensions: [ '.ts', '.js', ], }, };
この状態でコンパイルしてみる
以下のコマンドでコンパイルを実行する。
$ npm run build
以下の結果が表示される。
> sss@1.0.0 build /Users/user/Desktop/sss > webpack [webpack-cli] Compilation finished assets by status 0 bytes [cached] 1 asset ERROR in main Module not found: Error: Can't resolve './src' in '/Users/user/Desktop/sss' webpack 5.2.0 compiled with 1 error in 187 ms npm ERR! code ELIFECYCLE npm ERR! errno 1 npm ERR! sss@1.0.0 build: `webpack` npm ERR! Exit status 1 npm ERR! npm ERR! Failed at the sss@1.0.0 build script. npm ERR! This is probably not a problem with npm. There is likely additional logging output above. npm ERR! A complete log of this run can be found in: npm ERR! /Users/user/.npm/_logs/2020-10-24T12_07_51_536Z-debug.log
ERROR in main Module not found: Error: Can't resolve './src' in '/Users/user/Desktop/sss'
結果の中盤で以下のようなエラーが表示される。 これはどうやら、sssというプロジェクトにsrcというディレクトリが見つからなかったからエラーが出た。
てことでsrcディレクトリを実行する。
$ mkdir src
ついでsrc以下にコンパイル対象のtypescriptファイルを作成する。
$ vi src/main.ts $ vi src/sub.ts
再度コンパイルしてみる
$ npm run build
結果
> sss@1.0.0 build /Users/user/Desktop/sss > webpack [webpack-cli] Compilation finished asset main.js 827 bytes [emitted] (name: main) ./src/main.ts 1 bytes [built] [code generated] webpack 5.2.0 compiled successfully in 1729 ms
分かったこと
コンパイルが成功すると、プロジェクトルートにdistディレクトリが生成される。でjavascriptファイルが出力される。 出力ファイル名はどのようにして決定されるのか? これはどうやらwebpack.config.jsのoutputの項目で定めることができるのではないかと思われるが、実際に試せていない。
またwebpack.config.jsで定められるentryのキーはsrc以下にコンパイル対象のtypescriptファイルを指定する。
entry: './src/main.ts',
サンプルコードをおいておく
npmに関して分かったこと
右も左も分からないnpmについて少しずつ試してみて分かったことを書き溜める。
パッケージのバージョンを変更をする
1 package.json内のパッケージのバージョンを編集する。
$ vi package.json
2 変更を反映する
$ npm update
npm install について
npm installコマンドを実行すると、node_modules/.bin/にインストールしたものが追加されることを確認した。 確認時の結果を残しておく。
$ ls node_modules/.bin/ # webpackのパッケージがないことを確認 autoprefixer envinfo json5 sass tsserver browserslist errno nanoid semver webpack-cli cssesc import-local-fixture node-which tsc
そこでwebpackを追加してみる。
$ npm install --save-dev webpack # webpackの他依存関係のものも追加された
# 再度中身を確認する $ ls node_modules/.bin/ acorn cssesc json5 node-which sha.js webpack atob envinfo miller-rabin rimraf terser webpack-cli autoprefixer errno mkdirp sass tsc browserslist import-local-fixture nanoid semver tsserver # webpackが追加されていることが確認できる
sh: webpack: command not foundというエラーが出る
node_modules/.bin/にwebpackが追加されていなく、見つからないというエラーが出る場合があった。この場合にはwebpackをインストールすれば良い。
# webpackをインストール $ npm install --save-dev webpack
ERROR in Entry module not foundのエラーが出る
ERROR in Entry module not found: Error: Can't resolve '/Users/username/Desktop/try_typescript/myapp/static/myapp/js/index.ts' in '/Users/username/Desktop/try_typescript'
このエラーはwebpack.config.js内のentryで定めたコンパイル対象のファイルが見つからないときに表示されるエラーだと分かった。自分の場合には実際にコンパイル対象のindex.tsファイルを作っていなかったのでエラーが出てしまった。
ということでentryで定めたコンパイル対象のファイルを作成すればエラーは解消される
$ vi index.ts
webpackに関するメモ
webpackのバージョン確認方法
$ ./node_modules/.bin/webpack -v webpack-cli 4.1.0 webpack 5.2.0
webpackのバージョンはどうやら3と4系でwebpack.config.jsで書き方が変わるらしい。
npmのpackage.jsonについて分かったこと
package.jsonには、scripts項目が存在する。
どんなものか?
これはnpm runコマンドのあとに続行するコマンドを定義することができるようになる。
$ npm init
言うまでもないが、上記のコマンドを実行するとそのディレクトリにpackage.jsonというファイルが生成される。
少し分かったこと
scriptsには予約語が存在している。
- start,
- restart
- stop
- test
これが予約語である。しかしながらこれらの中身は決まっていないのでこれらの予約語には自分で中身をあてることになる。
その他にも自分で作ったキーをscriptsに追加する事ができる。
使い方は以下の通り。
$ npm run [スクリプト]
書き方
"scripts": { "start": "ng serve", "test": "ng test", "build": "ng build", "copy": "cpx ./dist/* ../server/", "precommit": "lint-staged", "ng": "ng", },
package.jsonのscriptに関する資料
typescriptメモ
基本の型(Basic Types, Primitive Type)
TypeScript: Handbook - Basic Types
- Boolean
- Number
- String
- Array
- Tuple
- Enum
- Unknown
- Any
- Void
- Null and Undefined
- Never
- Object
アロー関数の戻り値の型定義について理解していない。
環境構築
書いたtypescriptをjavascriptにトランスパイルするのでnpmが必要になる。
とりあえずdjnagoとtypescriptを共存させる環境を作ってみる。
参考とする記事:
【Django3.0】TypeScript と Sass でフロントエンドを書く【webpack4】 - AI can fly !!
環境
# 環境作成コマンド conda create -n try_typescript python==3.8 source activate try_typescript pip install django==3.0
# OSバージョン sw_vers ProductName: Mac OS X ProductVersion: 10.15.6 BuildVersion: 19G73
# pythonバージョン python -V Python 3.8.5
# djangoバージョン django-admin --version 3.0
環境構築コマンド
基本的なdjangoの下準備のコマンド(特にtypescriptに関係ない部分)
# プロジェクトの作成とその中でアプリを作成 mkdir try_typescript cd try_typescript/ django-admin startproject config . python manage.py startapp myapp
# config/settings.pyの編集(作成したmyappをプロジェクトに反映させる) vi config/settings.py # 以下のように追加 INSTALLED_APPS = [ "django.contrib.admin", "django.contrib.auth", "django.contrib.contenttypes", "django.contrib.sessions", "django.contrib.messages", "django.contrib.staticfiles", "myapp", # コレを追加 ]
# 親urls.pyの編集 vi config/urls.py # 以下のように編集 from django.contrib import admin from django.urls import path from django.urls import include # コレを追加 urlpatterns = [ path('admin/', admin.site.urls), path("myapp/", include("myapp.urls")), #コレを追加 ]
# 子urls.py(myapp/urls.py)の編集 vi myapp/urls.py # 以下のように編集 from django.urls import path from . import views app_name = "myapp" urlpatterns = [ path('', views.index, name='index'), ]
# views.pyを編集 vi myapp/views.py # 以下のように関数を設置する from django.shortcuts import render # Create your views here. def index(request): context = {} context["key"] = "value" return render(request, "myapp/index.html", context)
# myapp/views.indexが返すテンプレートを作成する mkdir -p myapp/templates/myapp vi myapp/templates/myapp/index.html # 以下のように記述 <h1>Hola!!</h1> <p>{{ key }}</p>
開発サーバーを起動させて動くか確認
python manage.py runserver # 起動後ブラウザで"localhost:8000/myapp"にアクセスし、作成したテンプレートが表示されればオッケイ
公開リポジトリ
GitHub - chiaki1990/base_dev_env: typescriptやvuejs環境構築練習用のベースリポジトリ
このコードをベースにtypescriptを共存させる手続きを加えていく
次にnpmをベースのコードに追加する
方法は以下を参考に。。。
node.jsのインストール方法(mac) - diadia
ベースのコードに追加する手続き(概要)
typescriptを使えるためにする手続きは以下の通りである
- npmコマンドを使って必要なパッケージを予めインストールする下準備
- 設定ファイルを調整する
上記の設定ファイルは、typescriptの詳細コンパイル設定を司るtsconfig.json、webpackの設定を司るwebpack.config.jsそしてnpm initで生成されるpackage.jsonである。
npmコマンドを使って必要なパッケージを予めインストールする下準備
$ cd try_typescript $ npm init
npm init コマンドはコマンド実行したディレクトリにpackage.jsonファイルを作成する。
もっと詳しくは以下を参考に。。。
フロントエンド開発の3ステップ(npmことはじめ) - Qiita
必要なnpmパッケージをインストールするコマンドとその理由
必要な npm パッケージをインストールする。
# webpackとwebpack-cliのインストール $ npm install --save-dev webpack webpack-cli
webpackにはいろいろな役割があるがコア機能はモジュールバンドラである。複数のjavascriptファイルを依存関係に従って一つのファイルとしてまとめ上げる。なぜ複数のjavascriptかといえばファイルごとに分けないとわけが分からなくなるから。でもファイルを分割すると読み込み順序に気をつける必要がある。この問題をwebpackは解決する。
# typescriptとtypescriptローダーのインストール $ npm install --save-dev typescript ts-loader
webpackの機能にローダーの機能があり、それを実現すためのローダー及びローダー対象をインストールする感じなのだろう。
上記はtypescript系のコマンド。
# saasとsassローダーのインストール $ npm install --save-dev sass sass-loader
webpackの機能にローダーの機能があり、それを実現すためのローダー及びローダー対象をインストールする感じなのだろう。
上記はsass系のコマンド。
# CSS関係 $ npm install --save-dev css-loader mini-css-extract-plugin postcss-loader autoprefixer
webpackの機能にローダーの機能があり、それを実現すためのローダー及びローダー対象をインストールする感じなのだろう。
@import などの依存関係の解決に css-loader 、CSS ファイルを出力するために mini-css-extract-plugin 、ベンダープレフィックスを付与するために postcss-loader と autoprefixer をインストールします。 ちなみに、ベンダープレフィックスの付与は必須ではありません。
この辺は深堀りしたいときにとっておく。
typescript初期化(tsconfig.jsonの作成)
# tscの実行 $ npx tsc init (# 以下のコマンドでも可) $ ./node_modules/.bin/tsc --init
npxはどうやらnpmでインストールしたパッケージを実行する際に使われる。npmでインストールしたパッケージを実行する際には"npm パッケージ"というコマンドは使えず、" ./node_modules/.bin/(パッケージ名) "のような形でパッケージを実行しなければならなかったんだけれども、npxを使うことでそういったパスを考えなくても直接パッケージを実行する事ができるメリットがあると分かった。npxコマンドが気に入らなければ、" ./node_modules/.bin/(パッケージ名) "を使ってtypescriptのパッケージを実行すれば良い。
tscを実行すると、tsconfig.jsonファイルが生成される。
このファイルの設定内容や設定オプションについても調べておく必要があるね。。。ちょっと大変。
tsconfig.jsonについてはどうやらtypescriptのコンパイルについて詳しく設定するためにあるファイルなのだろうと把握した。この設定詳細は公式ドキュメントにもあるし、qiitaの記事にもある。またtsconfig.jsonについて説明した記事も発見した。
tsconfig.jsonの設定項目の参考資料
TypeScript: Handbook - tsc CLI Options
TypeScript: TSConfig Reference - Docs on every TSConfig option
tsconfig.jsonの説明記事
tsconfig.jsonの全オプションを理解する(随時追加中) - Qiita
webpack.config.jsの設定内容
これは参考記事の内容をそのまま利用させてもらった。ここも詳しく理解しておく必要があるけどとりあえずdjango上でtypescriptを使えることが第一目標なので、必要になったら詳しく見ることにする。
# 手動でwebpack.config.jsを作成する vi webpack.config.js
const path = require('path'); const autoprefixer = require('autoprefixer'); const MiniCssExtractPlugin = require('mini-css-extract-plugin'); module.exports = { // モード mode: 'development', // エントリーポイント entry: { '[application_a]/static/[application_a]/js/main': path.resolve( __dirname, '[application_a]/static/[application_a]/js/index.ts' ), '[application_b]/static/[application_b]/js/main': path.resolve( __dirname, '[application_b]/static/[application_b]/js/index.ts' ) }, // ファイル出力先 output: { // 出力先ディレクトリ path: __dirname, // 出力ファイル名 filename: '[name].bundle.js', }, // ソースマップ devtool: 'cheap-module-eval-source-map', // ローダー module: { rules: [ { test: /\.ts$/, use: 'ts-loader', }, { test: /\.scss$/, use: [ { loader: MiniCssExtractPlugin.loader, options: { esModule: true, }, }, { loader: 'css-loader', options: { url: false, sourceMap: true, importLoaders: 2, }, }, { loader: 'postcss-loader', options: { plugins: () => [autoprefixer()], }, }, { loader: 'sass-loader', options: { implementation: require('sass'), sassOptions: { includePaths: ['./node_modules'], }, sourceMap: true, }, }, ], }, ], }, // モジュール解決 resolve: { extensions: ['.ts', '.js'], }, // プラグイン plugins: [ new MiniCssExtractPlugin({ moduleFilename: ({ name }) => `${name.replace('/js/', '/css/')}.bundle.css`, }), ], };
npm run biuldを実行するためにコンパイル対象ファイルを作成する
webpack.config.js内でentryを定めたが、それがコンパイル対象のファイルとなる。定めたファイルがない状態でnpmコマンドでコンパイルを実行しようとすると、エラーが生じてしまうことを確認した。したがって空ファイルでもいいからコンパイル対象のファイルを作成する。
vi index.ts
コンパイル実行
$ npm run build
コンパイルが成功する。
今回のコードをgithubに残す
https://github.com/chiaki1990/django_typescript_sample
今後の課題
typescriptをdjangoの中で使えるようになったわけだけれども実際にどうやって使っていくのかは分かっていない。 だからrest frameworkを使ってvueを使っていくのかとかそのへんを再度調べて形にしておきたい。
コマンドの種類について調べておきたい
npmはパッケージの管理を行うもの npxはパッケージを実行するためのもの
npm,npxについて解説してある参考資料
npm 5.2.0の新機能! 「npx」でローカルパッケージを手軽に実行しよう - Qiita
理解すると良いだろうということ
package.jsonで何を定めて、何ができるようになるかということ。どんな決まりで記述するのか等
djangoの構成を理解しておきたい。
エントリーポイントを後々理解しておきたい。 今回の場合はエントリーポイントは各アプリケーション下に存在する。index.tsという形で使われる。
webpackの具体的な用途
なぜ初心者は webpackが解らないのか?- Why can’t you understand the webpack? -
- typescriptのトランスパイル
- vuejs等のJSフレームワークの利用
- Sassの利用
- Linterを用いたjavascriptの構文チェック
webpackの基本的な要素
- Entry(エントリー)
- Output(アウトプット)
- Loader(ローダー)
- Plugins(プラグイン)
webpackは以下のurlが簡潔に説明されていてわかりやすい。
www.slideshare.net
バックエンドでKotlinをさわる
お世話になった本は以下。
入門!実践!サーバーサイドKotlin (技術の泉シリーズ(NextPublishing)) | 横山 恭大 | 工学 | Kindleストア | Amazon
androidアプリケーションでKotlinは使っていたけれども、主戦場にしたいバックエンドでKotlinが使えてないのは残念なので触ってみる。あとwebフレームワーク自体はdjangoしか触ったことがないので、他のフレームワークを触ることでどういう考え方が共通しているのか確認したい思惑がある。
Springframeworkについて
spring frameworkはフレームワークを束ねているものらしい。
その中から使いたいフレームワークを選択して構築していくらしい。
で、選択したフレームワークを実際に使えるように設定するには諸設定が必要になるようでそれが大変のよう。
その諸設定を簡単に解決する方法としてSpring Bootというフレームワークを使うようだ。これはSpring Initializerでファイルを生成し、それを使うとすぐ開発できるようになるといったもののようだ。
ビルドシステムについて
ビルドシステムはライブラリの依存関係を調整する機能とコンパイルする機能を持つ ビルドシステムにはAnt, Maven, Gradleといったものが存在する。JVM系の言語で開発する際にGradleといったビルドシステムにお世話になるのかなあと少ない経験から推測中。。。
プロジェクトの始め方
spring bootを使う場合プロジェクトの開始方法としてSpringInitializrを使う方法がある。
これは
https://start.spring.io/
にアクセスしてプロジェクトの条件を設定してやり、zipファイルを生成し、ダウンロードする。これを解凍し、そのディレクトリをIDEで開く(import)形で使用することだと分かった。
設定項目であるが、
設定項目 | 選択肢 | 自分が今回設定した内容 |
---|---|---|
project | Maven project またはGradle project | Gradle projectを選択 |
language | Java, GrrovyまたはKotlin | Kotlinを選択 |
Spring Boot | 様々なバージョンがある | バージョン2.3.4を選択 |
今気になったこと
- どういう感じでリクエストを受け入れるのか。 -> RequestMappingアノテーションを使ってurlを設定
- どうやってhtmlを返すのか?そしてそれはどこに格納するのか? -> いわゆるControllerを使うと設定できる。当初はurls.py, views.pyといったファイルで明確に分けられているものかと思ったけどそうではなく、url解決と何を返すかは同一ファイルで併存する形式を取る。
@RestControllerについて
「@RestController」は、viewに遷移せずメソッドの戻り値がそのままHTTPリクエストのレスポンスとなります。このため、APIのようにデータだけ取得したい場合に用いられることが多いです。
横山 恭大. 入門!実践!サーバーサイドKotlin (Japanese Edition) (Kindle の位置No.739-741). Kindle 版.
つまり@RestControllerはDjangoでいうHttpResponseクラスにが匹敵するものであると認識すればよいだろうか。
@RequestMappingについて
「@RequestMapping」についてです。こちらはリクエストを受け付けるパスを指定します。今回は「/」なので「http://localhost:8080」で受け付けます。「/hoge」にすると「http://localhost:8080/hoge」になります。
横山 恭大. 入門!実践!サーバーサイドKotlin (Japanese Edition) (Kindle の位置No.744-746). Kindle 版.
これはDjangoでいうurls.pyに該当するところだと思えば良いと思う。
djangoの場合はurlsの解決とその挙動を厳密に分けていたわけだけれどもSpring Bootはそこをきっちり分けていないことが特徴だとわかる。 またアノテーションを付けてurlsの設定をする辺りはretrofit2のような感じで、全然違和感はない。むしろ親しみがあるやり方だ。
import org.springframework.webのimportが上手くいかない
build.gradle.ktsに依存関係のライブラリを記述するスペース(dependencies)があるが、そこに下記の修正を加えること。
//implementation("org.springframework.boot:spring-boot-starter") //コメントアウト implementation("org.springframework.boot:spring-boot-starter-web") //追加
上記のライブラリを追加することで@RestControllerや@RequestMappingを使えるようになる。
Thymeleafについて
Spring Bootに使われるThymeleafはHTMLを返す役割を果たすことが分かった。djangoでいうrender関数のようなものだと現状理解して進めている。
@Controllerについて
HTMLを返す役割を担う。return でhtmlファイルを返す。
@GetMappingについて
RequestMappingとGetMappingの使い分けについてだけれども、おそらくRequestMappingの方はリクエストメソッドのGET以外に対応できると思われるけど、GetMappingはGetのみの対応になると思われる。GetMappingは@RequestMapping(method = RequestMethod.GET)のショートカットであるという説明している文章も見た。
Spring Boot組み込みのデータベースを使う際の手続き
プロジェクト作成時に行うこと
Spring Initilizerでプロジェクト作成時に以下を追加する。
DB接続情報
DB接続情報はapplication.propertiesに記載する。
spring.jpa.hibernate.ddl-auto=update spring.datasource.driver-class-name=org.h2.Driver spring.datasource.url=jdbc:h2:./h2db/db_example spring.datasource.username=username spring.datasource.password=password
DBテーブルを作成するには?
djangoの場合はmodels.pyに作成したいmodel(テーブル名)をmodels.Modelを継承した形式で定義した。 一方kotlinを使ったH2databaseの場合には、data classを使って定義する。
package com.example.hello_db_app.demo_db import javax.persistence.Entity import javax.persistence.GeneratedValue import javax.persistence.GenerationType import javax.persistence.Id @Entity //このアノテーションがあるとテーブルが作成される data class User( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id: Int = 0, var name: String = "" )
@Autowiredについて
依存性注入のアノテーションであり、該当するクラスのインスタンスをフレームワークが自動でnewして代入してくれます。今回は「UserRepository」のインスタンスになります。こうすることでテストを書くときにモックに置き換えやすくなったり、共通処理を追加しやすくなったりします。
横山 恭大. 入門!実践!サーバーサイドKotlin (Japanese Edition) (Kindle の位置No.915-918). Kindle 版.
とのことだったが、よく分からなかった。後にわかるだろうってことで今はパスする
@PostMappingについて
GetMappingと同じ類。RequestMappingでかつPOSTメソッドのみに対応するもの。
@RequestParamについて
これは指定した引数がリクエストパラメーターであることを宣言します。そのため「http://localhost:8080?id=10」として「@RequestParamid:Int」とするとidに10が渡ってきます。
横山 恭大. 入門!実践!サーバーサイドKotlin (Japanese Edition) (Kindle の位置No.922-924). Kindle 版.
djangoの場合では
class HogeView(View): def get(self, request, *args, **kwargs) ...
のような形でself.requestから取り出したり、urlパラメーターから取り出す処理をしていたけど入れ込むことに関しては特に意識しないでやっていた。 Spring Bootの場合には、リクエストパラメータを指定しなければいけないってことが違いであり、ポイントなのであろう。
Spring Bootでテストコード
やること。
- テストDBの準備
テストDBの準備
DBは/src/test/resources/application.propertiesの形で設置する。application.propertiesはオリジナルのファイルをコピーしてくれば良い。
ファイルには以下の内容を記述する。
spring.jpa.hibernate.ddl-auto=create spring.datasource.driver-class-name=org.h2.Driver spring.datasource.url=jdbc:h2:./h2db/test_db_example spring.datasource.username=username spring.datasource.password=password
spring.jpa.hibernate.ddl-autoの値をcreateにすることでテスト実行時に新たなテーブルが作成され、すべてのテストを0から始めることができる。spring.datasource.urlの値はテストデータベースのurlでこれは任意?の値で良いと思われる。
@RunWith(SpringJUnit4ClassRunner::class)について
これはテスト用のライブラリにJUnit4を使用するという宣言です。SpringBootはデフォルトでJUnit4が組み込まれています。
横山 恭大. 入門!実践!サーバーサイドKotlin (Japanese Edition) (Kindle の位置No.1005-1006). Kindle 版.
@SpringBootTestについて
これはテスト時にSpringBootが必要な機能を使用する宣言です。今回のテストコードではモックの生成に使用します。
横山 恭大. 入門!実践!サーバーサイドKotlin (Japanese Edition) (Kindle の位置No.1006-1008). Kindle 版.
@Beforeについて
テストメソッドが実行される前に呼び出されることを宣言します。これによりテスト前の下準備を済ませます。今回はモックを生成しています。
横山 恭大. 入門!実践!サーバーサイドKotlin (Japanese Edition) (Kindle の位置No.1008-1010). Kindle 版.
@Columnについて
このアノテーションはエンティティの定義(モデル)の定義で使われる。クラスのプロパティ名とテーブルのフィールド名が異なるときに使われる。
package com.example.app.bbs.domain.entity import java.util.* import javax.persistence.* @Entity data class Article ( @Id @GeneratedValue(strategy = GenerationType.IDENTITY) var id : Int = 0, var name : String = "", var title : String = "", var contents : String = "", @Column(name = "article_key") var articleKey : String = "", @Column(name = "register_at") var registerAt : Date = Date(), @Column(name = "update_at") var updateAt : Date = Date(), @Column(name = "user_id") var userId : Int? = null )
Spring BootのDBまわりについて推測
Spring BootでもORMをやりたい場合には、djangoっぽい下準備が必要になる。 まずモデル。モデルはテーブルに一致したモデルを作成しなければならない。このモデルに対応する言葉としてSping BootではEntityという言葉が使われているけれども要はmodelってことなのだろう。 djangoの場合はモデルさえ作ったら、views.pyで各モデルのインスタンスを呼び出すなり、初期化生成して、その後save()メソッドを使ってデータを永続化していた。Spring Bootではこの点で少し異なりEntityを定義しただけではデータを永続化する処理をいきなりすることができない。そこで必要な概念がRepositoryという概念。これは要するに上で作ったEntityを利用したインターフェースを作り、ORMを利用する下準備をする。djangoではdjango.models.Modelを継承したクラスさえ作れば良かったけれども、Spring Bootではまずテーブルに対応するEntityを作成する。そしてデータ操作を可能にするために作成したEntityを利用してRepositryを作る。こういった差異があるのではないかと現状推測している。 このRepositoryには種類があり、JpaRepositoryとCrudRepositoryの種類が存在していることを確認している。
参考
応用情報技術者試験の参考書を読むのメモ
掛け算とか割り算はどうやって実現しているか?
-> シフト演算を使って掛け算や割り算を行っている。
シフト演算...ビットの並びをまとめて左にずらしたり、右にずらしたりすることで元の値の2倍や1/2倍という計算を実現している。
テストケース設計手法:
同値分割 これはテストデータを自分で用意してそのデータを選んでテストして実際の結果を確認する手法なのだろう。テストデータは有効範囲のデータ、有効範囲外のデータを準備する。
UMLについて
参考:https://www.itsenka.com/contents/development/uml/
UML(Unified Modeling Language)は、様々な開発現場で使用されている設計書の書式を統一する目的で規定された言語で、1997年にOMG ( Object Management Group ) により標準化されました。 但し、UMLによる標準化はあくまで表記方法であって、開発手法の方法論ではありません。
表記種類 | 名前 | 説明 |
---|---|---|
構造に関する表記 | クラス図(Class Diagram) | クラス構造を表現します。 |
構造に関する表記 | オブジェクト図(Object Diagram) | クラスをより具体化したオブジェクトで表現します。 |
構造に関する表記 | パッケージ図(Package Diagram) | クラスなどをグループ化し整理された関係を表現します。 |
構造に関する表記 | コンポジット構造図(Composite Structure Diagram) | クラスやコンポーネントの内部構造を表現します。 |
構造に関する表記 | コンポーネント図(Component Diagram) | コンポーネントの内部構造ならびにコンポーネント間の依存関係を表現します。 |
構造に関する表記 | 配置図(Deployment Diagram) | システムの物理的な構成を表現します。 |
振る舞いに関する表記 | ユースケース図(Use Case Diagram) | ユーザなど外部からの要求に対するシステムの振る舞いを表現します。 |
振る舞いに関する表記 | アクティビティ図(Activity Diagram) | システムの実行における処理の流れや状態遷移を表現します。 |
振る舞いに関する表記 | 状態マシン図(State Machine Diagram) | イベントにより引き起こされるオブジェクトの状態遷移を表現します。 |
振る舞いに関する表記 | シーケンス図(Sequence Diagram) | クラスやオブジェクト間の応答を時系列で表現します。 |
振る舞いに関する表記 | コミュニケーション図(Communication Diagram) | クラスやオブジェクト間の関連と応答を視覚的に表現します。 |
振る舞いに関する表記 | 相互作用概要図(Interaction Overview Diagram) | 相互作用図(ユースケース図やシーケンス図など)を構成要素として、より広域な処理の流れを表現します。 |
振る舞いに関する表記 | タイミング図(Timing Diagram) | クラスやオブジェクトの状態遷移を時系列で表現します。 |
回路について
回路には組み合わせ回路と順序回路という2種類が存在する。
半加算器と全加算器 |加算器|説明| |------|-----| |半加算器|下位からの桁上りを考慮しない| |全加算器|下位からの桁上りを考慮する|
プロキシサーバの役割:
プロキシサーバは、内部ネットワーク内の端末からの要求に応じてインターネットへのアクセスを代理する装置です。単にプロキシともいいます。プロキシサーバを設置すると、キャッシュ機能によるレスポンス向上、認証やフィルタリングによるセキュリティ、内部ネットワークの秘匿化などの効果を期待できます。
NAPT
NAPT(Network Address Port Translation)は、プライベートIPアドレスとグローバルIPアドレスの相互変換するNATの考え方にポート番号を組み合わせた技術です。
ファジング
ファジング(fuzzing)とは、検査対象のソフトウェア製品に「ファズ(英名:fuzz)」と呼ばれる問題を引き起こしそうなデータを大量に送り込み、その応答や挙動を監視することで(未知の)脆弱性を検出する検査手法
ユーザインタフェースのユーザビリティを評価:
RDBMSのロック: 2種類ある。共有ロック、専有ロック。
種類 | 説明 |
---|---|
共有ロック | データを読込むときに使うロックで、資源がこの状態の場合は他のトランザクションによる更新処理ができなくなる(読込みは可能)。 |
専有ロック | データを更新するときに使うロックで、資源がこの状態の場合は他のトランザクションによる読込みや更新ができなくなる。 |
DB
主キーとするために列は制約(条件)を満たす必要がある。
制約種類 | 説明 |
---|---|
一意制約 | データに重複がなく必ず位置であること |
NOT NULL制約 | NULL値を許容しない |
外部キーに関する制約
制約種類 | 説明 |
---|---|
参照制約 | 外部キーに含まれる値は、参照先となる表の列内に必ず存在しなければならない |
これは何かというと、外部キーの値が存在しないものを他のテーブルで参照するために外部キーを登録したり、外部キーの値が他のテーブルで使われているにも関わらず、当該外部キー値を削除するような行為を制限するということである。
正規化
正規化の目的...データに矛盾や重複を生じさせないこと
正規形種類 | 説明 |
---|---|
第一正規形 | 繰り返し部分を分離させて、独立したレコードとした表 |
第二正規形 | 部分関数従属している列を切り出した形の表 |
第三正規形 | 繰り返し部分を分離させて、独立したレコードとした表 |
関数従属と部分関数従属の用語
用語 | 説明 |
---|---|
関数従属 | 主キーが決まれば列の値が一意に定まる関係 |
部分関数従属 | 複合キーの一部の項目だけで列の値が一意に定まる関係 |
ノイマン型コンピュータとは
ノイマン型(ノイマンがた、英: von Neumann architecture)は、コンピュータの基本的な構成法のひとつである。
ノイマン型コンピュータでは、記憶部に計算手続きのプログラムが内蔵され、逐次処理方式で処理が行われる。中央演算部、制御部、記憶機構、入力部、出力部の5つの部分からなり、プログラム実行時には、主記憶装置から演算制御装置へ命令やデータが記憶レジスタを経由して転送され、命令は、命令アドレスレジスタにセットされたアドレスに沿って逐次的に実行される。今日の一般的なコンピュータシステムのほとんどが、このノイマン型である。
レジスタとは
レジスタとは、マイクロプロセッサ(MPU/CPU)内部にある、演算や実行状態の保持に用いる記憶素子。最も高速な記憶装置だが、一般的なCPU製品で数個から数十個(容量に換算して数十バイト程度)と数が限られる。GPUなど特殊なプロセッサでは数万個(数百キロバイト)のレジスタを内蔵するものもある。
つまりCPU内部にある記憶装置。
で、レジスタって一言で言っても色んな種類がある。
プログラムカウンタはプログラムレジスタと呼んだり、命令ポインタとも呼ぶことがあるらしい。
命令レジスタは実行中の処理を記憶するレジスタ。 インストラクションレジスタ(IR)とも言うらしい。 プログラムカウンタから次にやることが書いてあるメモリの場所を取得して、やることをメモリから読み出して記憶する。メモリからやることを読み出すことをフェッチと呼び、メモリからフェッチしたやることを解析することをデコードと言う。
コンピュータの命令実行順序
- 命令フェッチ
- 命令の解読
- オペランド読み出し
- 命令の実行
みんなのコンピュータサイエンスを読んでみたときのメモ
**通読2回目 一回目では何を言っているのかほとんど理解できなかった。したがって読書で調べたこと、メモを残しておく。
第1章
「プールが温かければ、私は泳ぐ」の意味は、私は温水でしか泳がない、を示すわけではない。「冷たいプール」に関しては何も保証していません。
両条件を表現するには、双条件(biconditional)を使います。A↔B:プールが温かい場合にのみ、私は泳ぐ
2章 計算量
時間計算量とはなにか。
計算量の増加を記法 O記法で表現する。
計算量指数関数的に増加するアルゴリズムを避ける。
時間計算量:
時間計算量はT(n)と表現され、大きさがnの対象を処理するときにアルゴリズムが要する演算数を示します。
WladstonFerreiraFilho. みんなのコンピュータサイエンス (Japanese Edition) (Kindle の位置No.667-668). Kindle 版.
計算量は、書いたコードがどれだけ計算することになるかを計算すればよい。 で、計算する対象が大きくなるとどれだけ時間がかかるかは、T(n)を使って計算する。N/Mみたいな形で計算し、前提となる対象と比べて増えた計算対象がどれだけ時間がかかるか見積もることができるようになる。
計算にかかる時間について
多くのアルゴリズムでは、対象の大きさが増加すると、演算の数が急増します。たとえば、私たちのカードソートのアルゴリズムでは、ちょっとした演算で26枚のカードをソートできますが、2倍の52枚のカードではソートに4倍の演算が必要です。
WladstonFerreiraFilho. みんなのコンピュータサイエンス (Japanese Edition) (Kindle の位置No.656-659). Kindle 版.
時間計算量はT(n)で表される。
ある計算を行う際に計算対象によっては計算の時間が変わることがある。 計算の対象は最善、最悪、平均の場合に分けられ、最悪の対象(サンプル)を用いると常に信頼できる基準が得られる。
大きさnの対象に対して、要する演算数をカウントすることで、アルゴリズムの時間計算量を調べることができます。
WladstonFerreiraFilho. みんなのコンピュータサイエンス (Japanese Edition) (Kindle の位置No.686-687). Kindle 版.
本書では選択ソートを用いてアルゴリズムの時間計算量を調べる方法を説明している。
自分は選択ソートを知らないのでこれが何なのかわからなかった。
選択ソートに関する説明:
選択ソート(基本選択法)とは - IT用語辞典 e-Words
選択ソート(Selectionsort)を丁寧に 解説してみた by Python - アメリカの大学で奮闘中
選択ソートをpythonで表現する
def selectionsort(l): n = len(l) for index in range(n-1): least = index for x in range(index + 1, n): if l[x] < l[least]: least = x tmp = l[index] l[index] = l[least] l[least] = tmp return l if __name__ == '__main__': from random import shuffle l = list(range(0, 15)) lcopy = l[:] shuffle(l) print('Unsorted') print(l) assert l != lcopy print('Sorted') print(selectionsort(l)) assert l == lcopy
コードの説明
最初のforでリストのインデックスを定める。そのインデックスに未修正のリストから探しだした最小値を配置していく。こうすると、左から順番に最小値が並べられていく。
計算量の計算について
読んでも直感的にわかることはなかった。ここについては他の資料を探して以後理解に務めることにする。
戦略
アルゴリズム設計の戦略について考える章である。
- 反復処理
- 再帰処理
- 総当り攻撃
- バックトラック
- 発見的解法
- 分割統治法
反復処理による戦略は、条件が満たされるまで、たとえば、for、whileを使って処理を繰り返すことにあります。繰り返しの各処理は反復と呼ばれます。対象の最初から最後まで各要素に対して同じ演算を行うときに最適です
WladstonFerreiraFilho. みんなのコンピュータサイエンス (Japanese Edition) (Kindle の位置No.872-874). Kindle 版.
用語メモ:べき集合
べき集合とは部分集合の全体の集合のこと。例えば、{1,2,3}という集合があれば部分集合は以下になる。
{}, {1}, {2}, {3}, {1,2}, {1,3}, {2,3}, {1,2,3}。
そして冪集合は{}, {1}, {2}, {3}, {1,2}, {1,3}, {2,3}, {1,2,3}である。
べき集合を生成するスクリプトの書き方
Python 3.x - 冪集合の作成(Python3)|teratail
再帰処理
再帰処理を使う場合にはメモリを消費することになる。また直感的にわかりにくい。しかし高速に処理することができる。
総当たり攻撃
4章 データ構造について
重要な用語として抽象データ型(abstract data type, adt)とデータの構成(structure data)があることが分かった。
抽象データ型(AbstractDataType:ADT)は、所定のデータ型に対して意味をなす操作群の仕様に相当します。ADTは所定の型のデータを格納した変数に対して機能するインターフェイスとして定義され、これらによってデータがメモリ上にどのように配置されているか、どのように操作されているかという詳細はすべて隠されます。
WladstonFerreiraFilho. みんなのコンピュータサイエンス (Japanese Edition) (Kindle の位置No.1491-1494). Kindle 版.
おそらくこの文章はデータ型(文字列型、ブーリアン型、数値型)に対して操作する際に使われるインターフェースのことを抽象データ型と呼んでいると思われる。この抽象データ型があるおかげで、各データ型のデータ操作は一定の名前(操作名)でラッピングすることができるといったところか? データ型に対して抽象データ型が一対一対応していると思ったけど、この認識は誤りか??そもそも再利用するってどういう事??
抽象データ型の例
- 基本データ型
- 整数
- 浮動小数点数
- 文字列型
- 論理型
- スタック
- キュー
- 優先度付きキュー
- リスト
- ソート済みリスト
- マップ(辞書)
- 集合
データ構造(data structure)は、データ処理モジュールでのADTの実装手段を提供します。
AWS: Error creating VPCが出た
terraform applyを実行した結果以下のエラーが表示された。
Error: Error creating VPC: VpcLimitExceeded: The maximum number of VPCs has been reached. status code: 400, request id: c5e55b9d-d44d-437b-bcd3-2303794c1c46
上記リンク先には以下のことが書いてある。
The soft limit for VPC is 5 per region , how many have you used ? – Kush Vyas Aug 29 '18 at 6:30
実際リージョンでVPCを5個作っていた。削除した結果VPCを新たに作成できた。
以下awsドキュメント
https://docs.aws.amazon.com/ja_jp/vpc/latest/userguide/amazon-vpc-limits.html