アプリ開発サークル勉強会⑥ 開催日時 2021年2月5日(土) 7:00-9:00
JavaScript問題集
本日もこちらの問題やりました!
Q26-30 https://gist.github.com/kenmori/1961ce0140dc3307a0e641c8dde6701d
ファクトリ関数
ファクトリ関数とは・・一つのオブジェクトを返す関数のこと
オブジェクトプロパティを呼び出す場合、インスタンス生成をしないとプロパティ、メソッドを使用できませんが、
ファクトリ関数の場合は関数から返却されたオブジェクトをこのように生成なしで使うことができます。
function juice(name, con) { return { name, con, concentration() { console.log(con + name + 'juice'); } } } var appleJuice = juice('apple', '100%'); appleJuice.concentration();
結果
100%applejuice
コンストラクト関数
コンストラクト関数とは・・オブジェクトを使うときにインスタンス生成する関数
下の例だとJuiceにプロパティを設定してからインスタンス生成しています。
その後、concentration関数を呼び出します。
こちらのほうがみなれてますが、どちらが良いのだろう。。。
newやthisが無い分シンプルに書けるファクトリ関数のほうが見やすくてよさそう。
モジュール単位で考えると一つのオブジェクトにまとめたいのでコンストラクト関数なのかなぁ?
function Juice(name, con) { this.name = name; this.con = con; this.concentration = function () { console.log(con + name + 'juice'); } } var appleJuice = new Juice('apple', '100%'); appleJuice.concentration();
結果
100%applejuice
不変なオブジェクト
オブジェクトに値の設定、削除、追加できるかの設定をしたい場合に使います。
厳格モード状態の場合ですが、
オブジェクトを不変化した場合、不可能とされている動作、例えば設定できないのに設定しようとすると、エラーがでます。
封印されてることの確認ですね。
/// 厳格モード 'use strict'
freeze
不可:設定 削除 追加
var obj = { name: 'toku', age: 100 }; Object.freeze(obj); obj.age = 1; delete obj.name; obj.luck = 33; console.log(obj);
結果
{ name: 'toku' }
seal
不可:追加 削除
var obj = { name: 'toku', age: 100 }; Object.seal(obj); obj.age = 1; delete obj.name; obj.luck = 33; console.log(obj);
結果
{ name: 'toku', age: 1 }
preventExtensions
不可:追加
var obj = { name: 'toku', age: 100 }; Object.preventExtensions(obj); obj.age = 1; delete obj.name; obj.luck = 33; console.log(obj);
結果
{ age: 1 }
オブジェクトの生成
既存のオブジェクトを新しく生成する。
引数1に新しく生成するオブジェクトのタイプを指定。
引数2に新たにに生成するオブジェクトを指定。
Object.create(引数1,引数2)
生成時にですが、プロパティの属性を指定します。
全てのプロパティは属性を持っています。
プロパティの属性
configurable:true or false 削除の指定
enumerable:true or false列挙の指定
writable:true or false 書き込みの指定
value:値
developer.mozilla.org
var obj = { name: 'toku' } var newObj = Object.create({}, { name: { configurable: true, enumerable: true, writable: true, value: 'name' } }); console.log(newObj);
結果
{ name: 'toku' }
周知事項
参加者からの要望ですが、
* 開催する時間帯をずらしてほしい
* レビューの機会を多めにとるようにしてほしい
とのことなのでタイムスケジュールを変更してみました。
6:00-7:00 自主勉強タイム
7:00-7:30 勉強会開始
7:30-8:00 レビュータイム
8:00-8:40 学習
8:40-9:00 レビュータイム
次回からお試しでこのタイムスケジュールで開催してみようと思います。
アプリ開発サークル勉強会⑤ 開催日時 2021年1月30日(土) 7:00-9:00
JavaScript問題集
本日は1月最後の勉強会となりました。
サークルの皆様のおかげで無事1ヵ月勉強会を開催し続けることができて嬉しく思います!
今後は活動の幅を広げつつ続けていきたいと思います。
では問題集の続きをやっていきましょう。
Q21-25 https://gist.github.com/kenmori/1961ce0140dc3307a0e641c8dde6701d
Sort()について
配列に格納した値を昇順、降順に並べ替えて結果を表示したいときってありますよね??
JavaScriptにもSort()という並べ替えてくれる便利な関数があるので使ってみました。
developer.mozilla.org
ただし、癖があるので注意しないといけないようです。
要素を文字列に変換してから、UTF-16 コード単位の値の並びとして比較します。
どういうことかというと、
const array1 = [1, 30, 4, 21, 100000]; array1.sort(); console.log(array1);
これらの配列をソートした結果がこうなります。
> Array [1, 100000, 21, 30, 4]
ほんとうにソートされてるの??って最初は疑問に思いましたが、ドキュメントを読んで理解できましたが、UTF-16の並びだとこうなるようです。
仕様通りですね。
ただこのままだと癖が強すぎて使えないため、引数にcompareFunction
こちらの関数を使って比較してあげると昇順と降順が可能となります。
やっていきましょう。
数値のソート
array1.sort(function (a, b) { return a - b; }); console.log(array1);
結果こうなります。
[ 1, 4, 21, 30, 100000 ]
想定通りですね!
今回は昇順でソートしましたが、降順でソートしたい場合はa - b → b - a
値を入れ替えれば問題なく降順にできました。
次は文字の比較をしてみます。文字の比較の場合はこう書きます。
文字列のソート
array2 = ['e', 'a', 'd', 'b', 'c']; array2.sort(function (a, b) { if (a < b) { return -1; } if (a > b) { return 1; } return 0; }); console.log(array2);
結果
[ 'a', 'b', 'c', 'd', 'e' ]
a,bの値を比較して返却されてくる結果が負か正でどちらが大きいかの判別をするみたいですね。
こちらも数値の時と考え方は同じで不等号を反対にすると降順にできます。
sort使わずに自分で書くと結構大変なのでどんどん使っていきましょう。
カリー化 と部分適用について
部分適用とは 複数の引数をとる関数の一部の引数に実引数を適用する操作のこと
カリー化とは ja.wikipedia.org
複数の引数をとる関数を、引数が「もとの関数の最初の引数」で戻り値が「もとの関数の残りの引数を取り結果を返す関数」であるような関数にすること(あるいはその関数のこと)である。
最初の引数だけに 1 を適用すれば、インクリメント用の関数が簡単に作れる。
ユースケースとしては何かしらの同じような処理があるときに使えそうですね。
WikiPediaに載っていたこの仕様を実装してみましょう。
addStock
在庫数を引数の数だけインクリメントする関数
カリー化なしで書くとこんな感じになります。
const productName = { orange: 0, apple: 0, banana: 0 } function addStock(num, name) { return console.log(Math.floor(productName[name] += num)); } addStock(1, "orange");
addStockAll
在庫数を引数の数だけインクリメントする関数
こちらはカリー化した場合。
引数numに在庫数、引数nameに名前が入ります。
引数が最初の引数で、残りの引数をaddStockCurryで定義した関数内で取り、結果を返す。
引数を一つだけにしてaddStockに渡しています。
function addStockCurry(num) { return function (name) { return console.log(productName[name] += num) }; } addStockCurry(1)("orange");
部分適用
引数1の値が固定化されて、在庫に加算されます
var addStockCurry1 = addStockCurry(1); addStockCurry1("orange");
こちらは最初の引数に渡した値を全ての在庫に対してインクリメントした結果を返す関数。
引数に渡した1の値が部分適合にあたります。
Object.keys(productName).forEach(addStockCurry(1));
カリー化と部分適合による数値の固定化でスッキリしたコードが書くことができました。
カリー化参考サイト
AWS EC2にてyum updateできない場合
EC2にてyum updateできない場合
状況としてはCloudformationにてインフラを構築後にTeratermにてssh接続した後、
yum updateしましたが、installがうまくいかずエラーが発生。yum updateができませんでした。
AWS マネジメントコンソール上でEC2などを作成した場合、特に気にしなくても最低限動くような設定で作成してくれますが、
Cloudformationでインフラ構築をすると、各種設定を自分でしなければなりません。
エラー内容はこちらです。
yum(パッケージ管理システム)が置いてあるミラーリストに接続できていないようです。
接続できていない原因がわからないため調べました。 VPCにエンドポイントなるものを設定しないといけないみたい。
検索するとすぐに記事が出たため、結構よくあるエラーっぽい。
参考にした記事を読んでみましょう。
エンドポイント
Amazon LinuxおよびAmazon Linux2のyumリポジトリは、S3に存在します。 EC2インスタンスが所属しているVPCのエンドポイントが、 S3のyumリポジトリにアクセスできるようにポリシーを設定します。
なるほど。。ポリシー設定が必要なことがわかりました。
早速設定してみましょう!設定方法は記事参照。
設定が終わり、参考にした記事の通りにエンドポイントを作成してもう一度yum updateしてみましたが、ダメでした。
なぜ??もしかしたらルール設定ができていない気もするのでSecurityGroupとNetworkACLのルール確認。
Amazon S3 におけるエンドポイント - Amazon Virtual Private Cloud
SecurityGroup
アウトバウンドルールの見直し。
外側への通信手段がないためhttpを追加。
NetworkACL
デフォルト設定だとすべてのトラフィックを許可しているため問題ないのですが、
cloudformationで作ったときにssh接続のみ許可するようにしていたので、このままだとinstallできません。
というわけでルールを追加します。
カスタムTCPにてポート番号をLinuxのエフェメラルポートに設定。
installが結構遅めだったので1024-65535
にしても良いかも。
dev.classmethod.jp
yum update
実行。
yum update成功しました!
何かしら繋がらない時はSecurityGroupとNetworkACLの設定がおかしい場合が多いですね。
次はCloudformationで自動化していきます。
やることはエンドポイントの作成とポリシーの設定。
cloudformation
エンドポイントの作成の仕方
公式より引用
S3Endpoint: Type: 'AWS::EC2::VPCEndpoint' Properties: PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Principal: '*' Action: - 's3:GetObject' Resource: - 'arn:aws:s3:::examplebucket/*' RouteTableIds: - !Ref routetableA - !Ref routetableB ServiceName: !Sub 'com.amazonaws.${AWS::Region}.s3' VpcId: !Ref VPCID
PolicyDoucument
ここに記述していくようです。
ポリシーの設定の仕方を調べました。
PolicyDocument
Policyの設定が必要な場合はPolicyDoumentに記述していく。
今回の場合はS3にアクセスしたいのでポリシーを追加します。
こちらのPolicyDocumentは設定しなければfullAccessとなるため必須ではないですが、fullAccessでなくてよいので追加します。
サービスへのアクセスを制御するエンドポイントにアタッチするポリシー。ポリシーは有効な JSON フォーマットである必要があります。このパラメータを指定しないと、サービスへのフルアクセスを許可するデフォルトのポリシーがアタッチされます。
AWS Policy Generatorにて一度Policyを作成してからGeneratorにて作成したPolicyを参考にしながらcloudformationを作成していくと間違いがなくて良いかもしれません。
エンドポイント→ポリシー→ポリシーの編集
ポリシーの作成ツール
Generate Policyをクリック
こちらのPolicy Jsonを参考にして作成する。
めちゃくちゃわかりやすいですね!
cloudformationコード
エンドポイント
S3Endpoint: Type: "AWS::EC2::VPCEndpoint" Properties: PolicyDocument: Version: 2012-10-17 Statement: - Effect: Allow Sid: "AmazonLinux2AMIRepositoryAccess" Principal: "*" Action: - "s3:GetObject" Resource: - "arn:aws:s3:::amazonlinux.*.amazonaws.com/*" RouteTableIds: - !Ref PublicRouteTable ServiceName: !Sub "com.amazonaws.${AWS::Region}.s3" VpcId: !Ref VPC
AWS Policy Generatorにて作成したJsonを参考に書いてみましたが、公式ドキュメントに載っていた書き方とほぼ同じでした。
そのため、修正点は二つほど。
Sid: "AmazonLinux2AMIRepositoryAccess"
識別するためのID追加
Resource: - "arn:aws:s3:::amazonlinux.*.amazonaws.com/*"
こちらも同様
正直いらないんじゃないか?程度の修正。 公式ドキュメントすごい!
Amazon リソースネーム (ARN) - AWS 全般のリファレンス
NetworkACL
NetworkACLInboundRule01: Type: AWS::EC2::NetworkAclEntry Properties: NetworkAclId: Ref: NetworkACL Egress: false RuleNumber: 100 Protocol: 6 RuleAction: allow CidrBlock: 0.0.0.0/0 PortRange: From: 22 To: 22 NetworkACLInboundRule02: Type: AWS::EC2::NetworkAclEntry Properties: NetworkAclId: Ref: NetworkACL Egress: false RuleNumber: 101 Protocol: 6 RuleAction: allow CidrBlock: 0.0.0.0/0 PortRange: From: 32768 To: 61000 NetworkACLOutboundRule: Type: AWS::EC2::NetworkAclEntry Properties: NetworkAclId: Ref: NetworkACL Egress: true RuleNumber: 100 Protocol: -1 RuleAction: allow CidrBlock: 0.0.0.0/0
docs.aws.amazon.com
注意点としてはインバウンドか?アウトバウンドか?をEqress
にて指定してあげるくらいだと思います。
Eqressがtrueならアウトバウンド、falseならインバウンドとなる。
これで終了となります!インバウンドとアウトバウンドのルールにかなり詰まったので、もっと学習しないとだめですね。。
アプリ開発サークル勉強会④ 開催日時 2021年1月23日(土) 7:00-9:00
JavaScript問題集
今日もこちらの問題集をすすめていきました。
Q16-20 https://gist.github.com/kenmori/1961ce0140dc3307a0e641c8dde6701d
今までの復習問題が多かったので今回はQ20のクラスについてをまとめてみました。
内容はクラスについて。
JavaやC#と同じ感覚で使えそうなのでどんなことができるかをやってみました。
アクセス修飾子
こちらはpublicとprivateの2種類。
何も宣言しない場合はpublic
変数の前に#をつけるとprivateになるようです。
#name;
インスタンス生成した後.nameの形で呼び出せないため、getterを作成する。
Javaとこのへんは一緒ですね。
getName() { return this.#name; }
staticにもできる。
static country;
this
thisによる変数宣言。
コンストラクタにて呼び出すことで、クラス内に変数populationを後から追加できる。
thisを使った後から追加ではアクセス修飾子をprivateにはできないようです。
// population 追加するとこんな感じのイメージ constructor(country, name, population, citizen) { this.population = population; }
後からプロパティやメソッド追加
フィールドについては直感的に追加できる。
メソッドを追加するときはprototype.メソッド名で無名関数を代入するとクラス内に追加することができて、呼び出せるようになる。
クラス内に既に定義してあるフィールドやメソッドを使いたい場合は明示的にthisを使った指定をしないとエラーとなるため、注意。
どの場所のどの変数を使うかわかりませんもんね。
hyogo.prefecturalOfficeLocation = "kobeCity"; City.prototype.getNameAndPlace = function () { console.log(`県名:${this.getName()} + 市民名:${this.getCitizen().getName()} + 県庁所在地${this.prefecturalOfficeLocation}`); };
継承
インスタンス生成時に現在時刻を表示させるクラスを作成。
継承元にコンストラクタを定義した場合、
thisの前にsuper()で呼び出さないエラーとなるため注意。
super.メソッド名の形でメソッドも呼び出せる。
作成したクラス
GenerateTime
class GenerateTime { constructor() { console.log(Date()); } }
Cityクラス
class City { class City { // private // private thisへの追加によって後から追加できない。 static country; #name; population; #citizen // コンストラクタ constructor(country, name, population, citizen) { this.country = country; this.#name = name; this.population = population; this.#citizen = citizen; } // getter getName() { return this.#name; } // getter getCitizen() { return this.#citizen; } }
Cityzenクラス
匿名クラスにしてみました。
var Citizen = class { //private #name; #age; // コンストラクタ constructor(name, age) { this.#name = name; this.#age = age; } // getter getName() { return this.#name; } }
インスタンス生成 呼び出し
この辺もおんなじですね。オブジェクト 指向?? TypeScriptをやってみて比較してみるとわかりやすそう。
昔はクラスとかアクセス修飾子がなかったようなので、その時代なら。。。
クロージャを使ってもprivateを再現できるそうな。今度やってみます。
let hyogo = new City("japan", "hyogo", 100, new Citizen("Tok", 50)); let oosaka = new City("japan", "oosaka", 110, new Citizen("kty", 40)); hyogo.getCitizen().getName(); oosaka.getCitizen().getName();
参考サイト
C# プロジェクト、ソリューション、フォルダの名前変更
プロジェクト、ソリューション、フォルダの名前変更の仕方
ソリューション、プロジェクトを作成した後に名前変更の変更をしようとしたが、
詰まったので書きます。
名前をConsoleApp4 → ThreadPractice に変更したい場合。
ソリューションエクスプローラー→対象のソリューション or プロジェクトを右クリック→名前を変更
で名前を変更できますが、実はこれだけでは終わらない。
ファイルの中身が変わっていないんですよね。。
対象ファイルはこちらの2点。
①ThreadPractice.csproj
②AssemblyInfo.cs
ThreadPractice.csproj
こちらは何かしらのエディタを使って開く。(vscodeでもいいし、サクラエディタでもよし。
すると変更したはずのファイルが全く変わっていませんでした。
AssemblyInfo.cs
こちらはAssemblyTitleとAssemblyProductの名前が変更されていませんでした。
上記二つのファイルの名前をthreadPracticeに修正しましょう。
フォルダ
これで終わると思いきや、次はフォルダから開いてみましょう。
ソリューションエクスプローラー→プロジェクト→エクスプローラからフォルダを開く
フォルダが変更されていない???
どうやら自動でやってくれないようです。
フォルダの名前を変更してslnを開いてみましょう。
これで終わりかな??
プロジェクトを開いてみましょう。
アンロード
アンロード済みだと。。。
表示→プロパティウィンドウを開いてみましょう。
どうやら参照先が変更前の名前の状態のため読み込めなかったようです。
変更すれ問題ないので名前を変更しようとクリックしましたが選択できず変更できませんでした。
もう一度再定義したら大丈夫かな??なので一旦プロジェクトを削除しちゃいます。
安心してください!さっきの名前変更みたいに削除してもフォルダには残ってますよ!
※もしもの場合もあるかもしれないので念のためバックアップをとっておくか、gitなどでversion管理してる状態でやることおすすめします!
プロジェクト削除
ソリューションを右クリック→追加→既存のプロジェクト→ThreadPractice.csproj
無事プロジェクト、ソリューションの名前が変更されました。
長かった。。。
後から変更はかなりめんどくさいので、ちゃんと名前を考えてからプロジェクトを作成しましょうw
一個上の階層、ConsoleApp4フォルダも名前を変更したいんですけどこちらもはまったのでまた次回やりたいと思います。
参考サイト
参考サイト① qiita.com ファイルからではなく.netから変更する方法。
参考サイト②
yukamemo-ver3.blogspot.com
フォルダの名前が変わっていない問題。
AWS 謎の請求について。
謎の請求について
EC2インスタンスを停止状態、RDSに関しては削除してあるため請求はこないはずでしたが、なぜか請求が来ていたので調査しました。
AWS使用状況についてはこちらのサービスを確認。Billing and Cost Management
Billing and Cost Management
Route53はdomainを取得していてS3でサイトを公開しているため使っているので請求来ても問題ないのですが、
停止したはずのEC2と削除したはずのRDSが課金されているようです。
右上の料金明細をクリックして内訳を見てみます。
1. EC2(Elastic Compute Cloud)のEBS
EBSはEC2のデータを保存する領域のようで、インスタンスを止めていても保存されているデータがある状態だと課金されるようですね。
2. RDS(Relational DataBase Service)のAmazon Relational Database Service BackUp Storage
こちらはRDSを作成した際のBackUpファイルのようです。
削除する前にいつもスナップショット作って復旧できるようにしてたのを思い出しました。
用語についての詳しい内容はこちらを参考にしました。
www.bit-drive.ne.jp
EBS削除方法
EC2→Elastic Block Store→アクション→デタッチを選択→ボリュームの削除
RDSスナップショット削除方法
RDS→スナップショット→アクション→削除
FAQ
ドキュメントのFAQより読んでおくべき内容を抜粋しています。
ルールが詳しく書いてあるのでドキュメント大事ですね。
Amazon EC2 インスタンス時間はどのように請求されますか?
aws.amazon.com
請求の条件
* インスタンスが 1 時間単位で請求される場合、新しいインスタンスが起動されるたびに、つまりインスタンスが実行中状態になるたびに、最低 1 時間の料金が請求されます。
* インスタンスが秒単位で請求される場合、新しいインスタンスが起動されるたびに、つまりインスタンスが実行中状態になるたびに、最低 60 秒間の料金が請求されます。
インスタンスをすべて終了しているのに、Amazon EC2 の料金が請求されるのはなぜですか?
aws.amazon.com
請求される主な原因
* Elastic IP アドレス
* Amazon Elastic Block Store (Amazon EBS) のボリューム
追記
次の日Billing and Cost Managementを覗いてみるとまた増えている・・・ 笑
EBSのスナップショットが残っていたのが原因のようです。
AWS登録時の一年間は無料枠があるため何にお金がかかるのか調べないとわからないため、こういった請求がほぼないため今回非常に勉強になりました。
ただ長期間放置しちゃうとえらいめにあうので 、無料期間過ぎてる人は使い終わったサービスは削除しちゃいましょう。
アプリ開発サークル勉強会③ 開催日時 2021年1月16日(土) 7:00-9:00
JavaScript問題集
今日もこちらの問題集をすすめていきました。Q12-15
https://gist.github.com/kenmori/1961ce0140dc3307a0e641c8dde6701d
デフォルト引数について
デフォルト引数・・・引数に対して何も値を渡さなかったときにデフォルトで初期化される引数のこと。
function def(a = 5, b = 7) { return a + b;
def(1); 結果:8
関数defに1を引数と渡してあげるとaは1となり、
bは何も値を渡していないのでデフォルト値の7となる。その結果a+b = 8
function def(a = 5, b = 0) { return a + b; }
def(); <span style="color: #ff0000">結果:5</span>
デフォルト値にb=0設定することで値が無い場合も0となる。
デフォルト引数を使うメリットはnullとundefinedチェックが不要となりそう。
Q.13 next()を実行しただけ返り値が1増える関数を定義してください
答え
var count = 0; function next() { return ++count; }
next(); 結果:1 next(); 結果:2
グローバルな値として変数countを宣言して、
next関数を呼ぶたびにcountがインクリメントされる。
模範解答
const setUp = function () { let count = 0; return function () { return ++count; } };
const next = setUp(); next(); 結果:1 next(); 結果:2
1つ目の無名関数にてcountを宣言して、
内部の2つ目の無名関数でcountをインクリメントした結果を返す。
内部で変数countを宣言しているためnext関数をいくら呼んでも1のままに見えますが、
クロージャにより内部変数を永続化することによりインクリメントされるようです。
グローバル変数として宣言していくと、どこの処理に変数を使ったかわからなってくるので、
宣言した変数を他の処理で使いまわしをしない(1度しか使わない)場合に役に立ちそうな書き方。
無名関数
その名の通り、名前が無い関数。1度しか使わない場合に用いられる。
何度も同じソースコードや記述したり、名前を付ける必要が無くなる。
名前が無いため他の変数に代入しないと使えない。
error
function () { return "hello"; }
名前が無いためエラーが出ます。
ok
var greet = function () { return "hello"; }
名前をつけたのでOK
無名関数の中で無名関数をよぶ場合
var greet = function () { return function () { return "hello"; } }
var greet = greet();
2つ目の無名関数にも名前をつけると表示される。
クロージャ
内側の関数から外側の関数のスコープへのアクセスができる。
メリットは変数の永続化と隠ぺい。
変数の永続化により、外側で宣言したcountに内側からアクセスし、インクリメントした結果を返す。
通常なら内部の宣言した変数countをインクリメントしても永続化できないはずなので、できた理由はクロージャによるものです。