コーディング規約の重要性 

皆さん、こんにちは、入社2年目の鹿倉です。今回はコーディングの重要性を語ろうと思います。

コーディングとは

 コーディング規約の前にコーディングとは、何でしょうか。
 コーディングとは、プログラミング言語を使ってソースコードを作成する事です。曖昧な事ですが、詳細には、仕様書に沿って、ソースコードを作成して、ブラウザで見える化をする事です。
 読者は、あれ?、それってプログラムじゃないかと疑問に思っているかもしれませんが、実は、コーディングはソースコードを書く事だけを指しています。一方でプログラムは、書くだけではなく、設計したり、テストする事を指しているのです。

コーディング規約の重要性

 コーディングの意味を知った所で、いよいよコーディング規約を説明します。
 コーディング規約とは、開発者がプログラム言語でソースコードを記述する際に、形式や書き方を決める事です。簡単に言えば、プロジェクトで開発する際に、ソースコードの形式のルールを決める事です。
 実は、コーディング規約を決めるのは、とても重要な事なのです。何故なら、コーディング規約を決める事で、作業効率が上がる事が出来るからです。
 例えば、プロジェクトで複数メンバーで開発する際、メンバーそれぞれがコーディングを自由に書いたらどの様な事が起きるのでしょうか。
 他者のソースコードを見る際に独特なソースコードが書かれた場合、理解するのに時間が掛かる事でしょう。そうなると、理解するのに時間が掛かり、効率が悪くなってしまいます。それを阻止する為に、コーディング規約は、非常に重要なのです。

PHPにおけるコーディング規約の例

 では、実際にコーディング規約には、どんなルールがあるのでしょうか。
今回は、PHP言語で、コーディング規約の例を説明しようと思います。
 PHPのコーディング規約で代表的なのは、PSR-2 と呼ばれるコーディング規約です。この規約は、PHPでソースコードを記述する際に、PHPのコーディングスタイルつまり、形式についての規約が記載されています。では、PSR-2にはどの様なコーディング規約があるのでしょうか。

簡単なプログラミングを例に説明します。以下のプログラミングは、readline関数でユーザーのコンソールで年齢を入力したのが$ageに代入されます。その後、関数で年齢の範囲を判定して、関数の結果を出力しています。

■PSR-2のコーディング規約の一部の例

・if文の「{」の前では改行してはいけない。
・elseやelseifの前後括弧は同じ行に配置。
・else ifではなくelseifで1語でまとめられる様にする。
・インデント(字下げ)をする際は、半角スペースを4つ開ける。

ここに、記載されていている、PSR-2は、一部に過ぎません。
 他にも、PSR-2では、PHPのコーディング規約は多くあるので、以下のURLでも参考にしても良いと考えています。是非、参考にして見てください。

URL:http://www.php-fig.org/psr/

コーディング規約の記事を作成した考えた事

今回のコーディング規約について記載して思った事は、プログラマーは、決められたコーディング規約の中で最適なコーディングを書く事が重要だと考えました。
 ソースコードには、エラーが起こらない限り書き方は、自由です。しかし、自由にし過ぎると他者がソースコードを見た時に、理解出来るのかの方で重要です。
 そうしなければ、結局は、私しか理解する事が出来ないコードになってしまって、開発する際に、大きく足を引っ張ってしまいます。
 プロのプログラマーを目指す人には、ただソースコードを書くだけではなく、自分が書いたソースコードを他者に説明するスキルを身につける事が必要だと私は、考えています。

それでは、また、次の記事でお会いしましょう。アディオス!!?

新入社員ブログ 中島04 『PHPテキスト学習1』

こんにちは!そして明けましておめでとうございます。

22年度入社の中島です。

新年が明けたと思ったらもう一ヶ月が終わりました…
とても早い気がします。

『一月往ぬる二月逃げる三月去る』という言葉があるように、ぼーっとしていたらあっという間に四月になるかもしれませんね。

このままだとまずいと思い、今年の1月から技術力向上のためPHPのテキストで学習に取り組んでいます。

今回はその復習も兼ねて、簡単にブログにまとめていきます。

学習に使用したPHPのテキストはこのテキストです。

そして、学習した内容を大まかにまとめると

・PHPの基本
変数、定義、データ型、配列など

・演算子
代入演算子、比較演算子、論理演算子、ビット演算子など

・制御構文
if命令、switch命令、while/do命令、for命令、foreach命令など

・組み込み関数
文字列関数(mb_strlen関数、mb_substr関数、str_replace 関数)
配列関数(count 関数、array_merge 関数、implode関数)
正規表現(PCRE)関数(preg_match 関数、preg_replace関数、preg_split 関数)
ファイルシステム関数(fopen/fclose関数、fwrite関数、fgetcsv関数)

など現在進行形で学習しています。
そして表紙に書いてあるように
『手を動かしながら学ぶ』と書いてあるので、実際にプログラムを打って実行して動きを確認しながら学習しています。

[/crayon]

『テキストを読む』→『プログラムを打ち込む』→『プログラムを実行する』
この流れで学習を行い、理解できない部分は上司に聞いたりGoogleで調べながらより理解を深めていきます。
先ほどもお話ししたように現在進行形で学習中です。テキストのページも半分ほどでまだまだこれからなので、一生懸命取り組んでいきます。

今回はここまで
最後までご覧いただきありがとうございました!

[bug]マルチプロセスでlog4netのファイルローテーション時に一部ログが欠損して困った

福岡の香月です。

log4netのRollingFileAppenderを使って日付で出力ファイルが切り替わる設定をしていたところ、日付が変わって新しいファイルへの出力が始まると先頭に出力されるであろうログがなぜか出力されない現象に遭遇しました。
設定はこうです。
複数のプロセスで同じ設定を用いて、同じファイルに対してログ出力します。

[/crayon]

AppenderはRollingFileAppenderを指定しています。複数プロセスで使用するため、lockingModelはInterProcessLockを指定します。これによりファイルストリームを開きっぱなしにして、mutexで排他制御しながら末端にシークし書き込みを行うことで、複数プロセスから効率的にログ出力を行ってくれます。
複数プロセスから使う場合はこれ以外にもMinimalLockを指定できますが、書き込むたびにファイルのオープンクローズを実施するため速度が求められる場合は不向きでしょう。さらに複数プロセスからの出力が同時に走った場合、片方はオープンできないためログが出力されません。

この設定でビルドし、業務終わりにアプリを起動して一晩中実行させ、翌朝出社して確認しても日付が変わった後のログの内容が足りませんでした。
最初はlog4netの使い方が悪いのか、自分のプログラムにバグがあるのかさんざん悩んだんですがさっぱりわからない。トレース用に埋め込んだログも当然のように出ていないのでどうしたものかと思いました。

しかし、プロセスが1つの場合はちゃんと期待通りのログが出ていました。問題があるのは複数プロセスの場合だけだったのです。

そこでlog4netのロジックを確認することにしました。 幸いなことにソースはこちらから取得できます。
https://github.com/apache/logging-log4net
すると、ファイルが切り替わったあとは最後に書き込んだプロセスのログが先頭に来て、それ以前のログが破棄される作りになっていたのです。

少しずつソースを見てみましょう。今回使っているのはRollingFileAppenderです。日付が変わるときにファイルを切り替える部分は、RollOverTime()という関数であることがわかりました。こうなっています。
https://github.com/apache/logging-log4net/blob/master/src/Appender/RollingFileAppender.cs

[/crayon]

ふむふむ、SafeOpenFile()で新しいファイルをオープンしに行くわけね。そして第二引数がfalseと。そしてSaveOpenFile()の実態はベースクラスFileAppenderにありました。
https://github.com/apache/logging-log4net/blob/master/src/Appender/FileAppender.cs
ここから次の順番で呼び出されていきます。

  • RollingFileAppender.OpenFile()
  • FileAppender.OpenFile()
  • FileAppender.InterProcessLock.OpenFile()
  • FileAppender.LockingModelBase.CreateStream()
[/crayon]

ここでSafeOpenFile()の第二引数で指定されたfalseは、CreateStreamのappendに代入されていることがわかりました。この場合FileMode.Createが指定され、FileStreamインスタンスが作成されます。
ではこのFileMode.Createはどのような動きをするかというと、

オペレーティング システムが新しいファイルを作成することを指定します。ファイルが既に存在する場合は上書きされます。これには Write 許可が必要です。
FileMode.Create は、ファイルが存在しない場合は CreateNew を使用した要求、ファイルが存在する場合は Truncate を使用した要求と等価です。

https://docs.microsoft.com/ja-jp/dotnet/api/system.io.filemode?view=netcore-3.1

複数のプロセスでログ出力を行う場合、FileStreamを最後に作成するプロセスによりそれまでのプロセスが作成したログファイルの中身がTruncateされて、つまり削除されてしまうわけです。
発生している現象とも合致するのでこれが問題であることを確信しました。

対応するためにはRollingFileAppender.RollOverTime()から呼んでるSafeOpenFile()の第二引数をtrueに知ればよいわけです。実際に修正して確認してみると、見事欠損することなく必要なログが出力されていました。
めでたしめでたし。

なお、SafeOpenFile()はRollingFileAppender.RollOverSize()内からも呼び出しているのでここも忘れずにtrueに変更しましょう。

何度も同じフォーマットをコピペして編集したくない人の為に

沖縄拠点の久保田です。

何度も同じフォーマットをコピペして編集したくない人向けのテクニックを紹介したいと思います。

用意するソフトウェアは以下となります。

■必要な環境
Microsoft Excel 2016

まずは完成形から見ていきましょう。

※完成図

  1. [@雛形]セルの1つ下のセルに雛形を書きます。置き換えた対象となる部分に[@01]や[@02]のように設定します。
  2. [@値]セルの1つ下のセルに雛形で使用するパラメータ[@01]や[@02]を設定します。行を増やしながら埋め込みたい値を設定します。
  3. [実行]ボタンを押下後、クリップボードに出力結果が設定されます。

■クリップボードへの出力結果

[/crayon]

こんな感じのツールです。

何故このツールを作ろうと思ったのか

何故このツールを作ろうと思った経緯ですが、getter や setter を大量に半手動で作らないといけない事があり(今では便利なプラグインがあるのですが、)さらに、コメントも決まったフォーマットで書かないといけないという事がありました。

この時はインターネットにも接続できない環境で、必要なプラグインの入手までに時間がかかりました。(プラグインやツールの申請に1週間程かかりました)

例えば↓のような場合です。

[/crayon]

あー、もうこんなの手動で書くなんて信じられませんね。

getter, setter までは自動で出力してくれますが、コメントの形式までプロジェクトで決められていて、IDEの内包ツールではそこまで対応していませんでした。
手動でなんてやってたら時間かかるしミスは出るしで良い事なんて1つもありません。

そこで限られた環境で効率化を図る事にしたのです。

実際に作ってみよう

と、いうわけでここからは本ツールの作成方法を書きたいと思います。

※[開発]タブを使用しますので、表示されていない方は 、[ファイル] → [オプション] → [リボンのユーザー設定] の[リボンのユーザ設定]の[開発]チェックボックスをオンにして、事前に [開発]タブ を表示して下さい。

まず、下のような感じでシートを作成します。

[開発]タブ → 挿入 → フォームコントロール[ボタン]を選択して、任意の場所にボタンを配置します。

ボタンを配置するとマクロの登録画面になりますので、何も変更せず[新規作成]ボタンを押して下さい。

[ Visual Basic Editor ]が起動しますので、以下のソースを貼り付けて保存して下さい。
私の環境では Subプロシージャ [ボタン10_Click()]ですので、自身の環境に合わせて修正して下さい。

[/crayon]

[ Visual Basic Editor ] 画面 を閉じます。
では、先ほど配置したボタンを押してみましょう。メッセージボックスに「実行結果をクリップボードへコピーしました。」と表示されれば完成です。テキストエディター等に貼り付けして出力結果を確認して下さい。

■メモ帳に貼り付け結果

シートをコピーして増やすことで、雛形を多数準備する事も可能です。

作成にはVBAの知識が少し必要ですが、[マクロの記録]で必要なコードを収集しながら作成する事も可能ですので、是非VBAを使っていろいろ作成してみて下さい。

便利な使い方

便利な使い方をするには、まずインプットデータを本ツールにあまり加工せずに貼り付けできる状態が好ましいです。

例えばテーブル定義書です。

テーブル定義書のカラムの 物理名と論理名を使用して、コードとコメントを書く時に役に立ったりします。

エクセルなので当然セル内に関数を埋めこんだり、別シートのセルを参照したりできるわけで、それだけでも利用方法が広がると思います。

いろいろ工夫して使ってみて下さい。

<免責事項と注意事項>

本ページの内容について

  • 発生した一切の損害(機会の損失、結果的損害等を含む)について、いかなる責任も負いません。
  • ご利用は各個人での私的な使用に限るものとし、商用又は、営利を目的として、また公共の場での使用を一切禁止します。

C#でWOL(Wake-on-LAN)

福岡の香月です。

コロナ対応で世の中はリモートワークが進んでいるようです。中程度スペックの中古PCもたくさん売れているようで、在庫が少なくなっているようですね。

自宅作業する場合、会社のPCにリモートデスクトップでつないで作業することも多いと思いますが、気付いたらPCがシャットダウンしていることがあります。間違って電源切ったとか、夜中にWindows Updateが動いたとか。

そんな時はWOL(Wake-on-LAN)ですが、私はこれについて知識が無かったので調べがてらC#プログラムのWOLツールを作ってみました。プラットフォームは.Net Core 3.1です。
以下全文です。どん!

[/crayon]

特徴

  • マジックパケットを飛ばします。マジックパケットとは…
    • UDPで送信するパケット
    • 先頭6バイトに{ 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF }
    • 続けて対象PCのmacアドレスを16回
    • 合わせて102バイトのパケットとなる。
  • exeと同じ名前のiniファイルを設定ファイルとして読み込む
  • 設定ファイルにて以下を設定
    • host=対象PCのIPアドレス
    • post=UDPポート(ルータが許可したポートであれば何でもOK)
    • macアドレス=対象PCのmacアドレス
  • エラーが発生した場合はコンソール上にエラーを表示

プログラムは案外簡単でびっくりしました。
それよりもWOLが使える環境の設定が大変そうですね。BIOS、ネットワークカード、Windowsの設定など、情報はぐぐればいろいろ出てきますので一度お試しあれ。

nuxt.js環境を構築する

福岡拠点の野田です。

サーバーサイドでレンダリングするSSR(Server Side Rendering)を次の案件で使うことにしました。API側は慣れ親しんだLaravel。

最初に悩むのが環境構築。
どうしようか、というところで参考にしたのが、次の記事。

LaravelとNuxt.jsを同一レポジトリで管理するときの構成https://www.wantedly.com/companies/roxx/post_articles/84615

client フォルダ以下に環境を作る例ですが、とても参考になりました。以下おっかけになりますが手順になります。

[/crayon]

nuxtは起動フォルダ配下に.nuxtという一時ファイルを作成します。このため設定ファイルをclient以下に配置して、このフォルダを起動フォルダとします。

設定ファイル (nuxt.config.js)

[/crayon]

起動シェル(再起動シェル)は以下のような感じで作ります。

[/crayon]

ちなみにecho “” | はjenkinsから呼び出したとき、標準入力を要求されたので、それ対策で入れています。

このシェルを実行することでnuxt.jsサーバーが起動します。

nuxtは素のvueでやるよりも以下の点で優れていると思います。

  • 自動でルーティングしてくれる。
  • レイアウト機構を持っている。
  • API連携の仕組みも実装しやすい形で持っている。

VueやReactやAngularは、マイクロサービスをつなげる糊の役割をしているフレームワークだと思います。これからもっと深く使っていきたいと思います。

PHPUnit_その3(データプロバイダ)

福岡拠点の永嵜です。

前回に引き続きPHPUnitの機能を紹介します。

今回はデータプロバイダ機能を紹介します。
データプロバイダ機能とは、テストメソッドに任意の引数を渡せる機能です。
データプロバイダを使用すると同じテストメソッドで様々なテストができる利点があります。

データプロバイダ機能


例題を示しながら説明します。
前回使用したテストケースにデータプロバイダを追加します。

■テストケース

traiangleProviderメソッドがデータプロバイダになります。
[4, 2, 4]、 [4, 2, 10※1]がテストメソッドに渡す引数になります。
[横、縦、想定値]のデータをテストメソッドに渡します。
配列一つが1テスト用のデータになります。

※1  今回データプロバイダの説明のために想定値に誤った値を設定してテスト失敗を発生させています。

データプロバイダのデータにラベルを付けることができます。
(‘ok pattern’/’ng pattern’)
ラベルを付けることによってテスト失敗時にどのデータで失敗しているかを確認しやすくなります。
データプロバイダからデータを受け取るにはテストメソッドに@dataProviderアノテーションを付けます。

■実行

‘ng pattern’のデータでテスト失敗となりました。

また、実行時にfilterオプションを使用すると実行したいテストデータだけテストすることができます。

■データ指定(ok pattern)で実行

 

最後に

前回、今回、PHPUnitの概要を説明しましたが、PHPUnitには
コマンドオプション、アノテーション、アサーションなど他にも便利な機能があるので詳細を知りたい方は下記をチェックしてみてください。

PHPUnit マニュアル

https://phpunit.readthedocs.io/ja/latest/index.html

PHPUnit_その2(実行手順)

福岡拠点の永嵜です。

前回に引き続き、PHPUnitを紹介します。
今回はPHPUnitの実行手順を紹介します。実行環境は前回 Composer を使用してインストールした環境で行います。

PHPUnitの実行


PHPUnitでは理解するべき3つの要素があります。

①テスト対象クラス
ユニットテストを行うテスト対象のクラスです。

②テストケースクラス
テストケースは原則としてテスト対象クラスに対して1つ作成します。テストケース は、PHPUnit\Framework\TestCase※1 を継承して作成します。一般的にテストするクラス名の末尾に「Test」という文字列を付与したものをテストケース名とします(ファイル名はテストケースクラス名.php)。

    • テストケースクラス名 : 「[テストするクラス名]Test」
    • ファイル名 : テストケースクラス名.php

※1:vendorフォルダー配下にあります。

③テストメソッド
テストケース内に記述するメソッドです。実際にテストをする単位となります。
テストメソッドの名称は「test」で始まる文字列にする必要があります。
※@testアノテーションを使用する場合は、「test」でなくてもよいです。

では実際にテストケースを作成し、実行してみましょう。

まず、開発用ディレクトリにテスト対象クラスを格納する src ディレクトリとテストケースクラスを格納する test ディレクトリを作成します。

■テスト対象作成

テスト対象となるクラスを用意します。

引き数で横、高さを受け取り三角形の面積を返すクラスです。

■テストケースとテストメソッド作成

テスト対象が完成したらテストケースとテストメソッドを作成します。
test ディレクトリに AreaCalcTest.php ファイルを作成し、次のように記入します。

このテストケースでは、$width(横)と $height(高さ)で計算した面積が正しいかをテストしています。テストメソッドではアサーションと呼ばれる結果判定メソッドを使用します。今回の例ではassertEqualsがアサーションメソッドになります。
ちなみにassertEqualsは2 つの引数が等しくない場合エラーとするメソッドです。
$expectedに想定値、$actualに実測値を設定しassertEqualsで判定しています。

図1

図1のように開発用ディレクトリ(Sample)内にテスト対象(AreaCalc)とテストケース(AreaCalcTest)を配置しています。

■実行

phpunit コマンドを実行してユニットテストを行います。
phpunitはPHPUnitをインストールしたディレクトリのvendor\binフォルダ配下にシンボリックリンクがあります。

全てのテストケースの実行、特定のテストケースだけ実行どちらもできます。
今回はテストケースが1つですが①の方法で実行します。

①テストケースを全て実行する場合
・vendor\bin\phpunit  テストケース保存フォルダ
⇒例:vendor\bin\phpunit  test\

②テストケースを指定して実行する場合
・vendor\bin\phpunit  テストケース指定
⇒例:vendor\bin\phpunit  test\AreaCalcTest

※上記方法以外にもコマンドオプションで制御する方法があります。詳しくは PHPUnitマニュアルをご確認ください。

コマンドプロンプトを開き次のように入力します。
test ディレクトリ内のファイルをテストケースとしてテストが実行されます。

■テスト結果

テストが実行されるとテスト結果ステータス(4行目)が表示されます。
AreaCalcは正しい結果を返す状態なので( $width = 4、 $height = 2を引数で与えると4が返ってくる)テスト成功.(ドット)となっています。

他のステータス表示は以下のようになります。

ステータス 意味
.(ドット) テスト成功
F テスト失敗
E テストが危険としてマーク
S テストをスキップした
I テストが未実装

以上がPHPUnitによる一連のテスト手順となります。

次回は今回実行したサンプルプログラムに手を加え、
データプロバイダ機能について説明したいと思います。

PHPUnit_その1(インストール)

福岡拠点の永嵜です。

PHPUnitを使用する機会があったのでPHPUnitの使い方を紹介します。

本ブログでは下記の流れで説明していきます。
・PHPUnitの概要
・PHPUnit のインストール
・PHPUnitの実行

PHPUnitの概要


■PHPUnit
PHPで実装されたプログラムのユニットテスト(単体テスト)※1を自動化するためのテスティングフレームワークです。

※1:ユニットテスト
ユニットテストとはクラスや関数などプログラムを構成する小さな単位(ユニット)で個々の動作を確認するためのテストです。

PHPUnit のインストール


■PHPUnit のインストール
PHPUnitを使用するためにPHPUnitのインストールを行います。
インストールは下記方法があります。
・公式サイトから直接ダウンロードする。
・Composer を利用する

今回はComposerを利用した手順でインストールを行います。

①開発用ディレクトリに composer.json を設置し、次のように記入します。

②コマンドプロンプトで下記コマンドを実施します。

③インストール結果を確認します。
・開発用ディレクトリにcomposer.lock ファイルと vendor ディレクトリが生成されます。
・下記コマンドを開発用ディレクトリにで実行しPHPUnitが実行できることを確認します。
実行ができたらインストールしたPHPUnitのバージョンが表示されます。

以上がPHPUnitのインストール手順となります。

次回はPHPUnitを実行する手順について説明したいと思います。

PHP7の新規機能その2

福岡拠点の永嵜です。

前回に引き続き、PHP7.0以降に追加された機能を紹介します。

1.define() を用いた配列定数の定義
define() で配列の定数を定義できるようになりました。

サンプルプログラム
echoでANIMALSの要素1を出力しています。

 

2.use 宣言のグループ化
複数のクラスや関数そして定数を同じ namespace からインポートする際に、
単一の use 文にまとめられるようになりました。

サンプルプログラム

 

3.例外処理における複数の例外の catch
ひとつの catch ブロックで複数の例外を扱えるようになりました。
パイプ文字 (|) を使って指定します。
異なる例外を同じように処理したい場合に有用です。

サンプルプログラム

 

4.list() におけるキーのサポート
list() (あるいはその短縮版である [] 構文) の内部でキーを
指定できるようになりました。
list()及び[]で変数の中身を受け取る時もキーを指定した書き方が
出来るようになりました。

サンプルプログラム

実行結果

 

5.最後に
PHP7.0以降に多くの機能が機能が追加されています。
今回紹介した機能以外にも便利な機能が追加されていますので
詳細を知りたい方は下記をチェックしてみてください。

PHP マニュアル
http://php.net/manual/ja/migration70.new-features.php
http://php.net/manual/ja/migration71.new-features.php
http://php.net/manual/ja/migration72.new-features.php