月別アーカイブ 11月 2019

著者:杉浦

GitHubを使って一般的な変数名を選ぶ

 学生時代、分かりやすい論文を書くために気にするべきことの点として「一般的な語を選ぶ」という点がありました。ここでいう一般的とは、対象の界隈(論文なら学術分野)で広く使われていて共通認識が存在する、ということです。「一般的な語を選ぶ」とは、角速度センサとジャイロセンサの様な同じものを指す語の内より多く使われている方を選ぶ、といった感じの行為です。このどれが最も多く使われているかを簡易に調べる方法としてググった際のヒット件数の比較があります。界隈を限定するべき語(プログラミング言語のRubyと宝石のRubyを分けて検索したいとか)の場合は検索する語を追加したりGoogle Scholarまで行ったりします。先ほどの例ならばジャイロセンサの方が多く使われているので、角速度を計測するセンサを表す時は”ジャイロセンサ”を使うと判断できます。

 コーディングの際に気にするべきことに可読性、検索容易性があります。中長期の開発や機能改善の際にはいくらか忘却したコードを改めて読む必要があります。この時に変数名、クラス名などの様々な値の名前から値の意味が理解できない場合、コードを読み解くのに時間がかかります。また、ある機能について調べる時に値の名前から探そうとするもあり、一般的でない名前が使われているとまともに検索できません。次のツイートは極端な例ですが似たようなことは簡単に起きます。


 この様な名前の問題を避けるためにリーダブルコードでは次の様に指南されています。

名前をつけるときには、それが変数であっても、関数であっても、クラスであっても、同じ原則を当てはめることができる。名前は短いコメントだと思えばいい。短くてもいい名前をつければ、それだけ多くの情報を伝えることができる。プログラムに使われる名前というのはハッキリしないものが多い。例えば、tmpなんかがそうだ。でも、sizeやgetみたいに一見すると問題がなさそうな名前であっても、情報が含まれていないことがある。これから情報を詰め込んだ名前のつけ方を紹介する。本章は、以下の6つのテーマで構成されている。
– 明確な単語を選ぶ
– 汎用的な名前を避ける(あるいは、使う状況を選ぶ)
– 抽象的な名前よりも具体的な名前を使う
– 接尾辞や接頭辞を使って情報を追加する
– 名前の長さを決める
– 名前のフォーマットで情報を伝える

Dustin Boswell; Trevor Foucher. リーダブルコード (Kindle の位置No.228-232). 株式会社オライリー・ジャパン. Kindle 版.

 共通認識の成り立っていると仮定できるくらい一般的な名前ならば、少ない文字数で「明確な単語を選ぶ」「汎用的な名前を避ける(あるいは、使う状況を選ぶ)」「抽象的な名前よりも具体的な名前を使う」の三つが満たせます。また「接尾辞や接頭辞を使って情報を追加する」をした際に過度に長い名前ができあがらなくなります。
 論文における一般的な語の選択の様に、コーディングにおける一般的な名前を選択しようとするならば、コーディング界隈から使用されている数を調べる必要があります。この時、Googleは程々にしかあてになりません。Googleで検索できるのはweb上のコンテンツ全てでありソースコードから離れています。代わりにGitHubの様なソースコードリポジトリを用いることができます。特にGitHubならば言語、フレームワークでソースコードを絞り込むこともでき、より適した範囲から語の検索ができます。
 例えばJavaScript界隈で緯度経度を変数にするならばlat, lngにしておくのが適切だと分かります。

  • この記事いいね! (1)
村上 著者:村上

【Swift】NavigationBarのボタンアイコンがグレーになる時の対処法

再現するのがかなり限定的な時なのですが、私は地味に困ったので備忘録としてまとめ。
タイトル通り、ナビゲーションバーのボタンアイコンが、特に何も指定していないのにグレーになってしまう時の対処法です。
起動時にいきなりそうなるのではなく、別のページへ遷移した後に元のページに戻ってくると発生していました。
別にボタン自体はタップできるので、動作に問題はなかったのですが…やはり見た目が気になるのでどうにかしたい!

 

で、いろいろ確認したところ、アラートとページ遷移時のアニメーションが原因でした。
アプリで「接続中です…」というメッセージをアラートで表示し、画面遷移するときに消すという処理を実装しているのですが、ページ遷移の際にオプションの animatedfalse にしていたのが悪かったようです。
具体的に書くと下記の通りです。

// View を移動する.
self.navigationController?.pushViewController([遷移先のViewController], animated: false)  // 画面遷移時のアニメーションを無効にする

こちらのオプションを false にすると、画面遷移時のアニメーションが無効になるのですが、その場合、アラートが正しく閉じられていないようで…そのせいで、ナビゲーションバーのボタンのアイコンがグレーになってしまっていたようです。
多分ですが、アラートが表示されている間に表示されるグレーの透明背景の影響で他のボタンがグレーになっていて、それが残ってしまっているのだと思います。

なので、ちゃんとアラートを閉じてからページ遷移するサンプルコードはこちら。

// アラートを閉じる
alert?.dismiss(animated: true, completion: nil)
// View を移動する.
self.navigationController?.pushViewController([遷移先のViewController], animated: true)

ちなみに、アラートを閉じる時のオプションの animatedfalse にすれば、ページ遷移時の animatedfalse にしても大丈夫なのでは!?と思い試して見ましたが…こちらの方法では、相変わらずボタンアイコンがグレーになってしまい、ダメでした。
調べてみれば方法はあるのかもしれませんが、現時点で確実なのは上記の方法かと思います。
とりあえず、現在は特に問題はないので、この方法を使用したいと思います。

 

以上、ナビゲーションバーのボタンアイコンがグレーになってしまう時の対処法でした。
だいぶ限定的なので、他に活用できるかは分かりませんが…ご参考になれば幸いです。

  • この記事いいね! (0)
takahashi 著者:takahashi

jQuery MobileのAjaxLoadを完全に無効化する方法

スマホ向けデザインフレームワークのjQueryMobileには、すべてのページ遷移の操作をオーバーライドして、実際にページ遷移を行うことなくコンテンツの中身を遷移先のものに入れ替える”AjaxLoad”がデフォルトで有効になっています。

うまくやればページ遷移のエフェクトを含めたリッチなサイトも構築できるのですが、全ページで使用するアセットをランディングページ(サイトで一番最初に表示されるページ)になりうるすべてのページに読み込んでおかないといけないなどのデメリットがあり、こういったAjaxLoadの仕様に設計上対応できない(したくない)場合などに無効化したい場合があります。

ところが、jQueryMobileのバージョンで指定方法が異なったりなど、 確実に無効化する方法がわかりづらかったりするのが難点です。

今回はAjaxLoadを確実に無効化する方法をご紹介します。

結論から言ってしまうと、HTMLのheadタグ内に、下記のコードを埋め込むだけで無効化できました。

<script type="text/javascript">
    $(document).bind("mobileinit", function(){
        $.mobile.ajaxEnabled = false; 
        $.mobile.ajaxLinksEnabled = false; 
        $.mobile.ajaxFormsEnabled = false;
        $.mobile.loadingMessage = false;
        $.mobile.hashListeningEnabled = false;
    });
</script>

なお、

$.mobile.ajaxEnabled = false; 

は新バージョンの指定で、

$.mobile.ajaxLinksEnabled = false; 
$.mobile.ajaxFormsEnabled = false;

は旧バージョンの指定となっています。

両方入れておくことで、どのjQueryMobileバージョンであっても対応できそうです。

これらの指定を入れておくことで、この指定が入っているページについてはAjaxLoadが働かず、通常通りのページ遷移をさせることが可能です。

お困りの方は試してみてください。

  • この記事いいね! (0)
asaba 著者:asaba

【gradle】gradleのtask wrapperの書き方が変わっていた

build.gradleに書いてあるtask wrapper(type: Wrapper)は

gradle5.0から書き方が変わったらしく、そのままビルドすると

 


ERROR: Cannot add task 'wrapper' as a task with that name already exists.

 

エラーになってしまいます。

 

ここでは一番最初に記載されてあるtaskとtype:Wrapperを消去して

 


これを

task wrapper(type: Wrapper) {
gradleVersion = '5.4'
}

 


修正

wrapper{
gradleVersion = '5.4'
}

 

wrapperのみ記述することでエラーを回避することができます。

現状ではこの回避方法が無難かなぁと思います。

 

愚痴ですが、gradleのバージョンを上げなければandroidStudioでビルドしてくれない。

上げたら上げたでまた別の依存関係が出てくる(主にgoogle-serviceとか)

 

google-serviceの依存関係って本当面倒だ・・・。

 

  • この記事いいね! (0)
著者:杉浦

【Vue.js】コンポーネント外で定義した値をテンプレート内で使う

 Vue.jsの単一ファイルコンポーネントはコンポーネントを構成するHTMLテンプレート、JavaScript、CSSを一ファイルにまとめる仕組みです。コンポーネントの構成要素全体を把握しやすい点で優秀なのですが、テンプレート部で扱うことのできる変数が若干不透明で時として直感的でない振る舞いをします。
 次の例ではコンポーネント内全体がスコープっぽいところで変数hogeStrを宣言してテンプレート内で使用しようとしますが、これはhogeStrが未定義扱いされます。

<template>
  <div>{{ hogeStr }}</div>
</template>

<script lang="ts">
const hogeStr = 'hoge';

import Vue from 'vue';
export default {};
</script>

 実際に扱うときにはVueインスタンスの内部に含まれなければいけません。変化のない定数でも必須です。そのため実際は次のようにします。

<template>
  <div>{{ hogeStr }}</div>
</template>

<script lang="ts">
const hogeStr = 'hoge';
import fuga from 'fuga';

import Vue from 'vue';
export default {
  data() {
    return {
      hogeStr // 変化する値はdata
    };
  },
  computed: {
    nearMsgEnum, // 変化せず、getterのみでいいならcomputed
  },
};
</script>

 単一ファイルコンポーネントの作りではテンプレート、JavaScript、CSSがタグごとに分かれますが、結局のところtemplateタグもVueインスタンスの一部でありVueインスタンス外部を見るスコープにないようです。
 余談ですがdata, computedで同じ名前の値を読み込んでもVue.jsは動き続けます。外部から値を読み込むように作り替えた時に想定外の挙動が起きたならば、これが起きているのではないかと疑えます。

  • この記事いいね! (1)
村上 著者:村上

【Swift】URLSessionを使ってPOST送信を行う方法

ちょっと手こずったので、備忘録とコピペ元も兼ねてまとめ。
URLSession を使って Swift でPOST 送信を行う方法についてです。
こちらはログインページとかで使うことが多いと思います。

007 POSTを送信する・GitBook
http://docs.fabo.io/swift/connection/007_post.html

 

いきなり全コードを載せます。
ほぼ上記の参考サイトのコードをコピペしておりますので、そちらをご覧いただいてもOKです。
なお、ViewControllerURLSessionDelegateURLSessionDataDelegate を追加するのを忘れないようにしてください。

// 通信用のConfigを生成.
let config:URLSessionConfiguration = URLSessionConfiguration.background(withIdentifier: "login")
// Sessionを生成.
let session: URLSession = URLSession(configuration: config, delegate: self, delegateQueue: nil)
// 通信先のURLを生成.
let myUrl:URL = URL(string: "[POST先のURL]")!
// POST用のリクエストを生成.
var myRequest:URLRequest = URLRequest(url: myUrl)
myRequest.httpMethod = "POST"
// 送信するデータを生成、リクエストにセット.
let str: NSString = "username=\(username)&password=\(password)" as NSString
let myData: NSData = str.data(using: String.Encoding.utf8.rawValue)! as NSData
myRequest.httpBody = myData as Data

// タスクの生成.
let task: URLSessionDataTask = session.dataTask(with: myRequest as URLRequest)
// タスクの実行.
task.resume()

なおこちらはログイン時に使っている処理です。
各行で行なっているのはコメントに書いてある通りの処理ですので、それらを追ってもらえば大体内容は分かるかと思います。

個人的に詰まったのは 11行目からの送信するデータのセット部分です。
他に見た参考サイトなどの書き方ではうまくデータが送れず、かつ送信するデータが 1つだけの場合を想定したコードばかりだったので、上のサンプルコードのように、ユーザ名とパスワードなど複数データを送るときはどうしたら!?となっていました。
結論としては、送信したいデータを & で結合すればOKです。

なお、最後の行で task.resume() を行なった後は、下記のデリゲートが呼び出されます。

func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
    // 帰ってきたデータを文字列に変換.
    do {
        let json: NSDictionary = try JSONSerialization.jsonObject(with: data, options: JSONSerialization.ReadingOptions.allowFragments) as! NSDictionary
        // 後は任意の処理を実行
    } catch {
        print("parse error")
    }
}

私の環境では、POST送信した後に返ってくるデータは JSON だったので、NSDictionary 型の扱いやすい形にパースしています。
あとは、返ってきた値を保存するなど、行いたい処理を実行してください。

また、今回のサンプルコードでは使用していませんが、関数内で session.configuration.identifier を使うと、上のサンプルコードの2行目 URLSessionConfiguration.background で指定した Identifier を取得することができます。
同じページで違う POST 送信をする際でも、送信後に呼び出されるデリゲートは同一なので、こちらを使用して取得できる Identifier で処理の切り分けを行なっています。
なので、ログイン・ログアウトなど POST 送信後の処理が異なる場合は、違う Identifier を指定して、異なる処理を行えるようにしましょう。

 

以上、Swift の URLSession を使って POST 送信を行う方法でした。
ご参考になれば幸いです。

  • この記事いいね! (0)
takahashi 著者:takahashi

WindowsのHostsファイルに記述できるエイリアス名の上限

Windowsには自分のマシン内だけで使用できる存在しない仮のホスト名(ドメイン)をIPアドレスと紐づけたり、実在する ドメイン と対応するIPを別のものに書き換えたりすることができるhostsという仕組みがあります。

例えば、ドメインを取得する前に取得予定のドメイン名を使用してWebサイトが意図した動作をするか…などの確認に使えたりします。

Windowsのhostsファイルは次の場所に存在します。

C:\Windows\System32\drivers\etc\hosts

このhostsファイルですが、中身を見ると次のような書式になっています。

192.168.XXX.XXX example.com sub1.example.com sub2.example.com sub3.example.com

見方としては、一番左がIPアドレス、2番目が紐づけたいホスト名、そして3番目からはエイリアスとなるホスト名となっています。

ホスト名とエイリアスの違いはほぼありませんが、設定上の扱いは、2番目のホスト名が正式な名前で、3番目以降はこの正式なホスト名の”別名”という扱いになっています。

hostsファイルではサブドメインを登録する際に*(ワイルドカード)を使用することができず、使用する可能性のあるドメイン名をすべて列挙する必要があります。

別のレコード(行)に分けて書いてもいいのですが、同じIPに対して複数の異なる名前を付ける場合に全部別の行にしてしまうと見づらくなってしまうので、この場合はエイリアスを使用すると見やすくなります。

さて、このエイリアスですが、実は登録できるホスト名の数に上限があります。

HOSTS ファイルにおけるエイリアス名の最大数について – Microsoft

つまり一つのレコードにエイリアスを9個以上設定してしまうと。9個目以降はOSに認識してもらえず、設定されていないことになってしまいます。

そのため、9個目以降のホスト名でアクセスしようとしてもドメインが見つからない旨のエラーが出てしまいます。

この場合は9個目以降のドメインを別の行として書けば問題なく使用できるのですが、この使用を知らないとうまくいかなかったときちょっと焦ります。(僕は知らなくて一瞬焦りました…w)

hostsを使用して開発を行う場合は把握しておきましょう。

  • この記事いいね! (0)
著者:ym

パスワードは全部ランダムで

最近またパスワードの使い回しによる被害のニュースが増えている気がします。

対策としては SMS やメール、ワンタイムトークン等、多要素認証も重要があげられていますが、今の被害状況を見る限り、 人間には覚えられない様に毎回パスワードをランダム発行し、クラウド上に残らない、紙やメモ、ファイル等で保管することでほぼ防げると思います。

もしパスワードを保管するクラウドサービスを使う場合は、そのサービスに対しては多要素認証は必須。最悪、パスワードを保管するサービスが漏洩したときの対策も重要。

皆さんも、頭で覚えられるパスワードは設定しないでください。ながければ良いということでは無いが16桁位の英数大小記号入なランダムパスワードがおすすめです。

  • この記事いいね! (0)
村上 著者:村上

【Swift】presentで遷移した先のページにナビゲーションバーを表示させる方法

タイトル通り、Swift で作成したアプリで、present を使って遷移した先のページに NavigationBar を追加する方法です。
self.navigationItem.title でタイトルを表示したかったのにできず、地味に困っていたので助かりました。

参考にさせていただいた記事はこちらから。

【Swift3】 presentで画面遷移したときに遷移先のViewにNavigationBarを表示させておく – また1からこつこつと
http://mjk0513.hateblo.jp/entry/2017/03/31/011959

 

コードはこちら。

let nextPageController: NextPageController = NextPageController()
let navigationController = UINavigationController(rootViewController: nextPageController)
self.present(navigationController, animated: true, completion: nil)

ポイントは2行目で、単なるページ遷移だと 1行目で定義したコントローラをそのまま 3行目に渡して遷移させているのですが、上記のように 2行目にナビゲーションコントローラを間に挟むことで、ナビゲーションバーを設定することができます。
変更はこれだけ!
実際に実行したところ、遷移した先のページにナビゲーションバーが追加されていました!

 

以上、Swift で遷移先のページにナビゲーションバーを追加する方法でした。
ずっと遷移先のページで何かしらの設定をするものだと思い込んでいたので、遷移時にこうして設定するとは思い浮かばず…若干ハマりました。
swift navigationbar 追加」などで調べただけだと今回の手法にはなかなかたどり着けなかったので、同じことにお悩みの方のご参考になれば幸いです。

  • この記事いいね! (0)
著者:杉浦

【Vue.js】スプレッド構文と外部定義によるコンポーネントファイルの縮小化

 Vue.jsの単一ファイルコンポーネントはコンポーネントを構成するHTMLテンプレート、JavaScript、CSSを一ファイルにまとめる仕組みです。コンポーネントの構成要素全体を把握しやすい点で優秀なのですが、コンポーネントの構成要素全体を含むが故にファイルの肥大化を招きがちです。よくある肥大化を防ぐ方法の一つはコンポーネントに分割する粒度を細かくしていく方法です。理解しやすい方法なのでこれができるならこちらの方がいいでしょう。しかし分割困難かつ複雑なロジックを持つコンポーネントが現れる時があります。この状況に対応するため、ロジックを外部ファイルに定義、コンポーネントはロジックを呼び出すのみ、呼び出し方はスプレッド構文で安全に簡単に記述、という方法を考えます。
 スプレッド構文はJavaScriptの記法の一つです。正直滅多に使いません。
スプレッド構文 – JavaScript | MDN
 ここではObjectに関するスプレッド構文を扱います。動作は次の通り。public property限定の継承のといってもそう間違っていない印象があります。

var obj1 = { foo: 'bar', x: 42 };
var obj2 = { foo: 'baz', y: 13 };

var clonedObj = { ...obj1 };
// Object { foo: "bar", x: 42 }

var mergedObj = { ...obj1, ...obj2 };
// Object { foo: "baz", x: 42, y: 13 }

// https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Spread_syntax#Spread_in_object_literals
// スプレッド構文 - JavaScript | MDN#Object リテラルで使う

 注意点として浅いコピーなためコピーしたObjectとコピー元Objectの両方がネスト先の参照を共有する点があります。まあ不変な対象をコピーするならばshallow copyもdeep copyも変わらないのでそういう時は何も気にせず記述して大丈夫です。
 スプレッド構文を利用してVue.jsのコンポーネント中で定義を呼び出します。例えば、VuexのmapHoge系です。

computed: {
  // オブジェクトスプレット演算子で、外のオブジェクトとこのオブジェクトを混ぜる
  ...mapState({
    // ...
  })
  // コンポーネント個別のcomputedメソッド
  localComputed () { /* ... */ },
}
// https://vuex.vuejs.org/ja/guide/state.html#%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E6%BC%94%E7%AE%97%E5%AD%90
// ステート | Vuex

 Vuexのステート参照用メソッドを返すmapState関数の結果をスプレッド構文でコピーして、コンポーネント独自のcomputedメソッドと混ぜ合わせます。これでcomputedの中は次のように書いたのと同じになり楽できます。

computed: {
  // mapStateの結果が展開
  storeComputed1 () { /* ... */ },
  storeComputed2 () { /* ... */ },
  storeComputed3 () { /* ... */ },
  // コンポーネント個別のcomputedメソッド
  localComputed () { /* ... */ },
}
// https://vuex.vuejs.org/ja/guide/state.html#%E3%82%AA%E3%83%96%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%B9%E3%83%97%E3%83%AC%E3%83%83%E3%83%89%E6%BC%94%E7%AE%97%E5%AD%90
// ステート | Vuex
  • この記事いいね! (1)