![見出し画像](https://assets.st-note.com/production/uploads/images/97065999/rectangle_large_type_2_8cb6f5bf745db3c5e6a8086c93a02be8.png?width=1200)
【実践GAS6】リファクタリングとコードチューニングの勘どころ〜〜〜〜
概要
前回の記事
コードを見やすく安全に読みやすく分解する実践例を通じて、
なんかをしれっと示したんだけど、実はこれでやれば全部正解ってわけじゃないんだよね〜〜〜〜
で勘違いする人もいるかもと犬の散歩中に思ったので、
補足がてら、、、💦
特に
APIキーなんかを使ってスクレイピングするコードなんかで
もう4ヶ月以上離れていてうろ覚えだから、サンプル自体はあくまでもコード例になるんだけど
let sPage = 0;
let ePage = 100;
function APIキーでスクレイピング(){
for(var h = sPage; h < ePage; h++){
h層の処理...
for(i = 0; i < ilist; i++){
i層の処理...
for(j = 0; j < jList;j++){
j層の処理...
for(k = 0; k < klist; k++){
k層の処理...
}
}
}
}
}
みたいなコードがあるとして、
プロジェクトファイル内のデータをやり取りする分には問題が起きることは少ないけど、
スクレイピングの場合は、WEB上のデータを抜いてくるわけだから、この基本構文自体を下手に分割してしまうと、
呼び出し中にセッションが切れたりとかして、
セッションエラーでうまくスクレイピングができない
なんてことが出てくるので、
長いコードは全て分割すればいいわけではない
てのがあるし、
のどこかで書いてるはずなんだけど
コードのネストは深くても3階層まで
が鉄則なんで、実はこんなに階層が深くなる処理は基本的にコードとしては破綻しているんだよね〜〜〜
{
}
のかたまりをコードブロックなんて言い方をして、コードブロックをひとつの層としてカウントした場合、h,i,j,kで少なくとも4階層あるから、各階層の処理を別の関数を定義して、
let sPage = 0;
let ePage = 100;
function APIキーでスクレイピング(){
for(var h = sPage; h < ePage; h++){
h層の処理();
for(i = 0; i < ilist; i++){
i層の処理();
for(j = 0; j < jList;j++){
j層の処理();
for(k = 0; k < klist; k++){
k層の処理();
}
}
}
}
}
function h層の処理(){
処理
}
function i層の処理(){
処理
}
function j層の処理(){
処理
}
function k層の処理(){
処理
}
みたいな感じで、可読性を上げるとか再利用のために分割をした場合、
処理が期待値通りにいかないこともチラホラある。
しかも各階層の中にさらに、
let sPage = 0;
let ePage = 100;
function APIキーでスクレイピング(){
for(var h = sPage; h < ePage; h++){
h層の処理();
for(i = 0; i < ilist; i++){
i層の処理();
for(j = 0; j < jList;j++){
j層の処理();
for(k = 0; k < klist; k++){
k層の処理();
}
}
}
}
}
function h層の処理(){
for(var i = 0; i < iLast; i++){
処理1
for(var j = 0; j < jLast; j++){
処理2
for(var k = 0; k < kLast; k++){
処理3
}
}
}
}
function i層の処理(){
for(var i = 0; i < iLast; i++){
処理1
for(var j = 0; j < jLast; j++){
処理2
for(var k = 0; k < kLast; k++){
処理3
}
}
}
}
function j層の処理(){
for(var i = 0; i < iLast; i++){
処理1
for(var j = 0; j < jLast; j++){
処理2
for(var k = 0; k < kLast; k++){
処理3
}
}
}
}
function k層の処理(){
for(var i = 0; i < iLast; i++){
処理1
for(var j = 0; j < jLast; j++){
処理2
for(var k = 0; k < kLast; k++){
処理3
}
}
}
}
みたいな感じで、さらにネストがこんだけあったらもはや、なんの処理がどこに関連してるかすら、一読しただけでも収拾がつかなくなる。
まあ、高度なコードを書くことを信条にネストを深くして処理をわざわざ複雑にすることしか能がない人とかで多いんだけどね。
こんだけ深いネストで特に同時に処理をしなくていいなら、
処理自体を複数に分けるけどね、、、💦
コードのネストは深くても3階層まで
を知らない人が書いたコードで、最大5〜7階層までやってるコードを見たことがある、SQLだけどね笑
そんな処理を複雑にする暇があったら、
中間のファイル作る
か
作業カラム増やして
処理が終わったら消したほうが早えよ
て思ったけど。
よっぽどコンストラクションとかオブジェクト指向言語の再利用って概念を落とし込めてないからなんだろうね。
とにかく複雑なコードを書いて、2回や3回に分けても良い処理を1回で済ませようとか、部分的なコードの追記ばかりを繰り返して、コード自体がゲシュタルト崩壊してるような現場多すぎなんだけどね。
なので、結局
なんかで触れはしてるんだけど、
コードチューニング=アンチリファクタリング
で、
なんかでしっかり、
コードを組んだら期待値通りに動いているかをすぐに検証する
くせや体制づくりをしておいた方がいい。
まあ、かといって
リファクタリングしても問題ないことまで、コードチューニングで敢えて読みにくいハードコーディングなコードをそのまま残すことほど意味のないこともないけどね。
個人的な経験値としては、
スプレッドシート上の処理も含め、並列ではなく直列で分割できるようにして、
処理1(例:データをスクレイピングで一旦抜く)
↓処理2(例:抜いたデータをスプレッドシートに書き込む)
↓処理3(例:書き込まれたスプレッドシート上の値を取得して、計算など結果などを別のセルに書き込む)
て感じでネストを深くしなくて済むように設計を考えるのがオススメ。
処理(例:セルに書き込む計算結果が表示できるように計算しながら、データをスクレイピングで抜いた処理結果をスプレッドシートに書き込む)
も同じ処理結果を表してるんだけど、どっちが見やすいかだし、
どっちが、パソコンにも理解しやすいか。
て話。
なので、
//パラメータ
let sPage = 0;
let ePage = 100;
//メイン処理
function 集計処理(){
APIキーでスクレイピング();
スプレッドシートに書き込み();
スプレッドシートの値を取得して計算結果を書き込み();
}
function APIキーでスクレイピング(){
for(var h = sPage; h < ePage; h++){
for(i = 0; i < ilist; i++){
for(j = 0; j < jList;j++){
for(k = 0; k < klist; k++){
データ取り込み処理...
}
}
}
}
}
function スプレッドシートに書き込み(){
処理...
}
function スプレッドシートの値を取得して計算結果を書き込み(){
処理...
}
みたいな感じで、ネストは深くても、関数で呼び出しもせずに処理はひとつしか入れないな。
ネストを深く深くして同時に処理しようとする人ほど、なんでもいっぺんに処理したがるせっかちな人が多くて、
しかもそういう人ほど、
なんかで書いてる二次元配列で処理速度を100倍くらい早くできるやり方を知らなかったり、設計を練ってからコードを書いてないから、改修方法が分からなかったり。
で書いたリファクタリングの方法やコードの可読性を上げる方法も知らなかったりするからね。
今回の格言
既存のコードがあろうがなかろうが、必ずそれが唯一絶対の答えではない。
処理を分割しても影響がないのであれば、ネスト自体を分割する。
ただし、分割して問題がないか、期待値どおりになるかは、変更直後に必ず検証して確認すること🕺
コンストラクションに答え行こ正解なんざない
さてと、
GASから離れてはや5ヶ月目〜〜〜
今はiOSに夢中だし、もう記憶も薄れてきてるので〜〜〜
大体、現地で磨いた勘や知識は全て書き出せたかな。
後は、今までの記事を読んで応用すればできると思うし。
ではでは、
GASに関してはとりあえず一旦以上かな💦
SwiftUIのマスターマインドの学びに戻る〜〜〜🕺
この記事が気に入ったらサポートをしてみませんか?