学生プログラマはプログラミングバイトをしよう

 今回の記事に出てくる「学生プログラマ」には高校生は含まれておりません。高校生は労働基準法で勤務時間が制限されてしまう為、プログラミングバイトが難しいと思われるからです。

 しかし、100%不可能であるとは断言出来ないので、メンタルの強い方は挑戦してみてもいいかもしれません。(責任は取れません)

 

独学には限界がある

 プログラミングをしている学生さんは、独学や学校の授業でプログラミングを学んだことでしょう。自分で処理を考えて思った通りに動作した時は、何よりも気分が良い物だと思います。 

 しかし学生でプログラミングの勉強をしていると、下記のことに悩んだりしたことがあると思います。

  • 実際のシステムがどうコーディングされているのか
  • チームで開発をするときはどのように進めればよいのか
  • 自分のコードの書き方は本当に正しいのか  
  • 今の技術レベルは、業界的に見たらどれくらいなのか 

 そんな時は実際にIT企業にインターンやアルバイトに行き、現場のシステムやプロジェクトに触れてみることが良いと思います。

 自分の中の勝手なイメージですが、学生プログラマの方々は勉強会やコンテスト等には参加していても、プログラミングバイトをしている方は少なく思います。

 勉強会へ行くことは確かに大切ですが、実際に利益を生んでいるシステムの開発に関わることはより価値のある経験だと考えています。

 

プログラミングバイトはどうやって探す?

 プログラミングのバイトは「バイト探しはan」「マイナビバイト」等の普通のアルバイト求人サイトで応募しても、学生である以上ほとんど受かりません。

 自分は高校三年の冬に三社のIT企業に応募しましたが、悲しいことに三社とも面接さえ受けさせてもらえませんでした。常識的に考えれば、高校生が業務で役に立つとは思えないので正しい判断であると言えますが。

 完全に心が折れていましたが、Twitter で上記の経験を嘆いていると優しいフォロワーさんが素晴らしいサイトを教えてくれました。

 そのサイトは Wantedly というもので、学生プログラマのアルバイトやインターンを募集している企業が多く集まっているそうです。

www.wantedly.com

 早速このサイトである企業に応募してみました。すると、その企業の方は自分と会って話がしたいと言って下さったのです。学生というだけで話させて貰えない経験を3回もしていたので、すごく嬉しかったです。

 面接は新宿のカフェで行われ、IT関係で働いているプロの方といろいろなお話をしました。結果的に不採用となってしまいましたが、プロの方とカフェでお話するのはとても貴重な経験で楽しかったです。

 その後立て続けに7社の企業に応募し、2社から内定を頂くことが出来ました。このような経緯を経て、自分は現在web系の企業でアルバイトとして働いています。

 

学校に行きながらいつ働いているのか

 自分は平日週5日、放課後の 18:00 - 23:00 に働いています。また、自宅での作業も許可されているので、働くのが苦だと感じたことは一度もありません。

 全ての企業がこうであるとは言えませんが、Wantedly に登録している企業のほとんどは相談してみれば遅い時間帯であっても働かせてもらうことが出来ると思います。

 

まとめ

 ホリエモンビル・ゲイツも、学生時代はプログラミングバイトをしていたそうです。プログラミングバイトは技術に関してだけではなく、仕事に対する姿勢やエンジニアとしての物の考え方を身につけることもできます。また、周りの人が大人ばかりなので、人間的にも大きく成長出来ます。

 今の自分よりも更に上を目指したいと思っている学生プログラマの皆さんは、是非一度プログラミングバイトを経験してみると良いでしょう。

JQuery との別れ

 こんにちは、専門学校に通いながらwebエンジニアのバイトをしている者です。
普段考えていることや、新しく知ったこと等を適当にブログに書いています。
今回は JQuery についてです。

 自分は趣味でwebページを作ることがあり、ページ内のロジックに JavaScript を使用しています。(当たり前ですが)

 その際に自分は JQuery を使用していたのですが、 最近 JQuery はあまり使うべきではないという話をよく耳にしており、何故ダメなのか疑問に思っていました。 そこで、JQuery のデメリットや、JQuery を使わない場合等をネットで調べたり、会社の先輩に聞いてみたりしました。

 また、今回の記事は私見が多く含まれているので、あくまで考え方の一つとして捉えていただけたらと思います。

JQuery はスコープがでかい

 JQuery を使うとDOM全体を操作出来てしまう為、JavaScript の長いコードを修正する際にコード全体を読まなければならないそうです。 また、対象の要素の親要素を操作出来る .parent() 等のメソッドを使用してしまうと、コードの修正がとても大変になってしまうみたいです。

 これらの原因は、JQuery のスコープが大きいことにあります。 ですので、本来webページのロジックを記述する時はページ内のコンポーネントごとに行うことが理想です。 もちろん JQuery でもコンポーネントごとにコードを書くことも出来ますが、 全体を操作出来るメソッドが存在する以上、見づらいコードが生まれてしまう可能性は潰せないようです。

じゃあどうすればいいのか

 生の JavaScript か、フレームワークを使うと良いとのことでした。
生の JavaScript は面倒なことが多いですが、可読性は高いようです。

 また、フレームワークを使用すれば、ページ内のパーツをコンポーネントに分けて開発できるので、 スコープを縮めることが出来ます。

 JavaScriptフレームワークは一度も使ったことが無かったので、現在開発しているwebアプリケーションに組み込んでみようと思っています。

まとめ

 JQuery さよなら。

 

ある男の為に自作楽曲配布サイトを作る

 Googleアドセンスの申請を通したくて久しぶりに記事を書きました。

 自分は現在、IT系の専門学校に通いながらIT系のアルバイトをしています。 もちろん趣味でもプログラミングをしており、最近はアルバイトの影響でweb系の勉強を多くしています。 アルバイトではバックエンドの仕事が中心ですが、趣味ではバックもフロントもやってます。 しかし、勉強するだけでは本質的な技術は身につかないと思ったので、実際にwebサービスを作ることにしました。

 webサービスを趣味で作った経験はまるで無いので、とりあえず簡単なサービスから作りたいなと思っていました。 そんな時、高校の頃の同級生が学校にも行かずにひたすら曲を自作しているというので、まずはそいつの為のサイトを作ろうと思いました。

 サイトの機能は、楽曲再生・ダウンロード・コメント の3つが中心です。 たったこれだけなのかと思うかもしれないですが、 データベースを使ったり、動的にサイトを書き換えたりという処理をしたのは人生で初めてだったので苦労しました。

 バックエンドは FuelPHP というフレームワークを使用し、フロントでは当然ながら JavaScript を使用しています。 バックエンドに Rails ではなく PHP を選んだ理由は、環境構築が圧倒的に楽だったからです。 Rails が強力なフレームワークであることは理解していますが、趣味で使うにはまだ知識が足りないなぁという印象でした。

 公開するためのレンタルサーバは、Xサーバ の一番安いプランを利用しています。 一番安いとは言っても、個人が趣味で作った小さなwebサービスを公開する分には十分使えます。 料金の支払いは高校の同級生と割り勘です。

 このサイトは8割近く完成しているので、今月中には公開出来るだろうと思います。 公開しましたら、是非曲を聴いてくださると嬉しいです。

 ある男の Twitter@k_t_mejohn

 ある男が作った曲 → 作った曲

セキュリティ・キャンプ 2016  選択問題解答

 ブログでセキュキャンの解答を晒している方が何人かいらっしゃったので、自分も晒してみようと思います。 ここ違くね?とかここは同じだ!とか思っていただければ幸いです。

選択問題1

 実行結果のアドレスのサイズを見る限りですと、上記のプログラムは64bit の OS で実行されているのではないかと考えました。

 理由は、32bit の OS で上記のプログラムを実行した際は上記の実行結果よりも小さなサイズであり、 64bit の OS で実行した際は上記の実行結果に近いアドレスとなったからです。

 32bit の OS で実行した結果は下記の通りです。

hoge address = 0019F824
fuga address = 002D3208

 他に感じたことは、スタックとヒープのおおよその先頭アドレスがわかるので、上記のアドレスの差から これら2つの領域に割り当てられているアドレス領域のサイズがわかるのでは無いかということです。 「おおよその」というのは、ヒープに OS の管理領域がある為、正確な位置がわからないという意味です。

選択問題3

 パソコンの電源が入るとまず、システムBIOSがハードウェアを初期化して記憶装置からブートローダを読み出します。 そして読み出されたブートローダMBRに記録されているプログラムを呼び出し、呼び出されたプログラムはOSを読み込んで起動します。

 OS起動後に何かプログラムを実行させる時は、補助記憶装置に書き込まれたプログラムを実行することになります。 しかし問題文にあるようにCPUは主記憶上のプログラムしか実行できないので、 プログラムローダと呼ばれるものが必要に応じて、補助記憶装置に書き込まれているプログラムを主記憶装置に読み出しています。

 その後、プログラムローダは読み出したプログラムの先頭アドレスに飛ぶことで、目的のプログラムが実行されています。 以上の処理が行われているため、私たちは補助記憶装置に書き込んだプログラムを実行することが出来ています。

選択問題4

 プログラムは Windows Vista 32bit版 で Microsoft Visual C++ 2010 Express で作成・実行しました。 最初はこの問題を解こうとは思っていなかったのですが、チノちゃんが目に入ってきて問題を解くことを決意しました。 ソースコードは下記の通りです。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>

#define TRUE  1
#define FALSE 0

#define MAX_MAGIC       2
#define MAX_SOURCE      20
#define MAX_DESTINATION 20

/* バイトオーダーの違いを吸収する */
typedef union{
    unsigned int  byte_4;
    char          byte_1[4];
}byte_union;

/*------------ 
 | その他関数 |
  ------------*/

/* 文字列を小文字に変換 */
void str_to_lower(char *str,int size){
    int i;
    for( i=0 ; i<MAX_SOURCE+1 ; i++ ) str[i] = tolower(str[i]);
}

/* バイトオーダー変換 */
void change_byte_order(byte_union *data){
    const int INT_SIZE = sizeof(int) - 1;
    byte_union tmp_data;
    
    // バイトオーダー変換
    int i;
    for( i=0 ; i<4 ; i++ ) tmp_data.byte_1[i] = data->byte_1[INT_SIZE-i];
    
    // 代入
    data->byte_4 = tmp_data.byte_4;
}


/*-------
 | 条件 |
  ------- */

/* Magicの検証 */
int Condition1(char *data){
    if( strcmp(data,"RH") == 0 ) return TRUE;
    else                         return FALSE;
}

/* Sourceの検証 */
int Condition2(char *data){
    str_to_lower(data, MAX_SOURCE);
    if( strcmp(data,"rise-san") == 0 || strcmp(data,"cocoa-san") == 0 ) return TRUE;
    else                                                                return FALSE;
}

/* Destinationの検証 */
int Condition3(char *data){
    str_to_lower(data, MAX_DESTINATION);
    if( strcmp(data,"chino-chan") == 0 || strcmp(data, "chino") == 0 ) return TRUE;
    else                                                               return FALSE;
}

/* data に valid_order_brand が含まれているか検証 */
int Condition4(char *data){
    const char *valid_order_brand[3] = {
        "BlueMountain",
        "Columbia",
        "OriginalBlend"
    };

    int i=0;
    for( i=0 ; i<3 ; i++ ) if( strstr(data,valid_order_brand[i]) != NULL ) return TRUE;
    return TRUE;
}

/* data に invalid_order_brand が含まれていないか検証 */
int Condition5(char *data){
    const char *invalid_order_brand[2] = {
        "DandySoda",
        "FrozenEvergreen"
    };
    
    int i=0;
    for( i=0 ; i<2 ; i++ ) if( strstr(data,invalid_order_brand[i]) != NULL )  return FALSE;
    return TRUE;
}

/*-----------  
 |メイン関数 |
  -----------*/
int main(void)
{
    // 変数宣言(ファイルからデータを読み込む変数は、読み込んだデータを文字列として扱うために \0 の領域分を確保している)
    char Magic[MAX_MAGIC+1];
    char Source[MAX_SOURCE+1];
    char Destination[MAX_DESTINATION+1];
    byte_union DataLength;
    char *Data;
    int  byte_count = 0;
    int  pass_flag  = 0;
    int  loop_count = 0; // ループ回数を出力するためのもので、ループ処理には使用されない
    
    // 条件が全て通ったときの pass_flag の値
    const int PASS_FLAG_COUNT = 4;

    //ファイル読み出し
    FILE *fp;
    fp = fopen("pyonpyon.rh","rb");
    if(fp == NULL){
        printf("ファイル読み込み失敗\n");
        exit(0);
    }
    
    // ファイルサイズ取得
    fpos_t fsize = 0;
    fseek(fp,0,SEEK_END);
    fgetpos(fp,&fsize);
    fseek(fp,0,SEEK_SET);
    
    // ファイル終端まで読み出す
    while( byte_count < fsize ){
        // データ読み込み変数初期化
        memset(Magic,'\0',sizeof(Magic));
        memset(Source,'\0',sizeof(Source));
        memset(Destination,'\0',sizeof(Destination));
        
        // 一連のファイルを読み出す
        fread(Magic,sizeof(char),MAX_MAGIC,fp);
        fread(Source,sizeof(char),MAX_SOURCE,fp);
        fread(Destination,sizeof(char),MAX_DESTINATION,fp);
        fread(&DataLength.byte_4,sizeof(int),1,fp);
        // pyonpyon.rh はビッグエンディアンだが、windowsはリトルエンディアンなので変換する
        change_byte_order(&DataLength); 
        Data = (char *)calloc(DataLength.byte_4+1,sizeof(char));
        fread(Data,DataLength.byte_4,1,fp);
        
        // バイトカウントに読み込んだバイト数加算
        byte_count += MAX_MAGIC + MAX_SOURCE + MAX_DESTINATION + sizeof(int) + DataLength.byte_4;
        
        // 判定
        if( Condition1(Magic) )                       pass_flag++;
        if( Condition2(Source) )                      pass_flag++;
        if( Condition3(Destination) )                 pass_flag++;
        if( Condition4(Data) && Condition5(Data) )    pass_flag++;
        
        // ループカウント更新
        loop_count++;

        // 結果出力
        if( pass_flag == PASS_FLAG_COUNT ) printf("%2d回目:PASS\n",loop_count);
        else                               printf("%2d回目:REJECTED\n",loop_count);

        // メモリ開放 & paa_flag初期化
        free(Data);
        pass_flag = 0;
    }
    
    fclose(fp);
    return 0;
}

実行結果

 1回目:PASS
 2回目:PASS
 3回目:PASS
 4回目:PASS
 5回目:PASS
 6回目:PASS
 7回目:PASS
 8回目:PASS
 9回目:PASS
10回目:REJECTED
11回目:PASS
12回目:PASS
13回目:PASS
14回目:REJECTED
15回目:REJECTED
16回目:PASS
17回目:PASS
18回目:PASS
19回目:REJECTED
20回目:REJECTED
21回目:REJECTED
22回目:PASS
23回目:PASS
24回目:PASS
25回目:REJECTED
26回目:REJECTED
27回目:REJECTED
28回目:REJECTED
29回目:PASS
30回目:PASS
31回目:PASS
32回目:REJECTED
33回目:REJECTED
34回目:REJECTED
35回目:REJECTED
36回目:REJECTED
37回目:PASS
38回目:PASS
39回目:PASS
40回目:REJECTED
41回目:REJECTED
42回目:REJECTED
43回目:REJECTED
44回目:REJECTED
45回目:REJECTED

選択問題6

 まず簡単なシステム構成の前提ですが、ユーザ認証等の処理に使用する言語は PHP で、ユーザ情報を保存するデータベースは MySQL です。

 上記の構成でユーザ認証のWebアプリを構築した場合、自分が一番最初に行うセキュリティテストは「SQLインジェクション」の対策が行われているかどうかのテストです。 SQLインジェクションを選択した理由は、攻撃者が手軽に実行できる攻撃でありながら、 開発者はフレームワーク等を使用していない場合は自ら対策を行う必要があるからです。

 また開発者側がSQLインジェクション攻撃の存在を認識していても、サニタイズを忘れてしまう可能性もあります。 以上のような理由から、私は最初のセキュリティテストに「SQLインジェクション」の対策を行うことを選択しました。

FuelPHP でカラムを追加した時にやり忘れたこと

 現在使用しているテーブルに新しくカラムを追加したのですが、 何故かコントローラからモデルオブジェクトを呼び出してカラムを使おうと思っても上手くいかなかったので、 同じ事象に遭遇した人の為に記事を書きました。

 この問題はモデルのprotected static $_propertiesがカラム追加をしても更新されない為に起こる問題でした。 protected static $_propertiesコマンドラインでモデルを作成すると自動的に作られます。

 下記のように新規に追加したカラムをprotected static $_propertiesに追加することで解決しました。

protected static $_properties = array(
    'id',
    'カラム名',
    'created_at',
    'updated_at'
);

protected static $_properties = array(
    'id',
    'カラム名',
    'created_at',
    'updated_at',
    '新規カラム名'
);

無料サーバ Hostinger で FuelPHP を動作させる

 Hostingerは無料で使用できるレンタルサーバです。

www.hostinger.jp

 このサイトの他にもいくつか無料のレンタルサーバは存在しますが、大抵は広告がついていたりデータベースが使えなかったりと制限が多くあります。

 しかし、このサイトにはそのような制限はありません。なおかつ、使いやすいダッシュボードに充実したサポートもついているのですごく気に入っています。 ただし、無料なのでページが表示される速度は物凄く遅いです。まぁ、お金を払えば100倍早く出来ますが。

 もちろん、PHPも動作するので今回はこのレンタルサーバFuelPHP を動作させてみようと思いました。 なお、FuelPHP のプロジェクトは実際に動作する状態になっていると想定します。

 関係無いですが、Hostinger は残念ながら Ruby on Rails には対応していないようです。。。

まずはアカウント取得

 1.まずはトップページにアクセスして、アカウント取得。

 2.登録したメールアドレスに登録完了メールが来るので、アカウントを認証。

 3.次に、表示されているページで一番左の Free コースを注文し、適当に設定。

 4.これでサーバが使えるようになった、試しに登録したドメインにアクセスしてみる。(登録に時間がかかる場合もある)

ローカルの DB を Hostinger に移行する

 Hostinger 上ではマイグレートをすることが出来ないので、ローカルでマイグレートしておいて DB をエクスポートします。

 1.ローカルで phpMyAdmin を開き、プロジェクトに使用しているデータベースを選択して出てきたメニューから「エクスポート」をクリック。

 2.デフォルトの設定のまま「実行」をクリックすると、SQLファイルがダウンロードされます。

 3.Hostinger のダッシュボードから「MySQLデータベース」を選択し、適当な名前でデータベースを作成します。

 4.データベースが作成できたらダッシュボードから「データベースの読み込み」を選択し、先ほどエクスポートしたSQLファイルを読み込ませます。

 これで、データベースの移行は完了しました。

FuelPHP の環境設定をステージング環境に変更しておく

 FuelPHP には下記の4つの環境が設定されています。

  • 開発環境
  • ステージング環境
  • テスト環境
  • 本番環境

 ステージング環境とは本番環境でテストする時に使い、テスト環境は自動化テストを走らせる時に使うって考えています。 環境を変更するメリットは、環境ごとに DB に関する設定をする必要が無いからです。

詳しくは、ウェブ開発で大切な3つの環境を見てみると良いかも。

 今回の場合はステージング環境だと判断したので、FuelPHPの環境をステージング環境に切り替えます。 切り替えるにはfuel/app/bootstrap.phpFuel::DEVEROPMENTFuel::STAGINGに変更。 すると、下記のようになるはずです。

\Fuel::$env = (isset($_SERVER['FUEL_ENV']) ? $_SERVER['FUEL_ENV'] : \Fuel::STAGING);

ステージング用の DB 設定を編集

 環境をステージングに変更しただけでは何も意味無いので、ステージング用の DB 設定ファイルを編集していきます。

fuel/app/config/staging/にあるdb.phpの内容を、Hostinger で作成した DB の設定に変更しま。 なお、作成した DB の設定はダッシュボードの「MySQLデータベース」から確認できます。

FuelPHP のプロジェクトを Hostinger に移行する

 FuelPHPに限った話ではないですが、フレームワークを使用したwebサイトは全体の容量が大きくなります。

 ですので、Hostinger に FuelPHP のプロジェクトをアップロードするためにはサイトのファイルマネージャーでは無理なので、FTPクライアントを使用する必要があります。

今回私が使ったのは、FileZillaです。

使い方は超初心者向け!FileZilla(ファイルジラ)の使い方を参照してください。

FTPアクセスに関する情報は、ダッシュボードの「FTPアクセス」に記載されています。

アップロードするディレクトリは、public_htmlです。


 これで FuelPHP を動作させることが出来ると思われます。

何かわからないことや、間違っていることがあれば是非コメント下さい。

 最後に気がついたのですが、本番環境にアップロードする時はpublic以下をドキュメントルートに設定しましょう。

Rails c や PHP oil c が結構役立つ

 今までweb開発をしていてあまりコンソールを使うことがなく、何のためにあるのだろうと思っておりました。 しかしここ最近頻繁に使うようになったので、自分の使い道をいくつか列挙しようと思います。

 因みに、Rails cRuby on Rails で、PHP oil cFuelPHP です。

=====についての検証

 同値判定は言語によって癖があり、Rubyでは1=='1'TRUEだっけ??みたいなことがよく起こります。

そんな時、Rails cなどでコンソールを開いて実際に確認してみたりします。

メソッドの戻り値

 FuelPHPUpload::save()は何を返すんだっけ?っと思ったことがあり、webページ上に echo Upload::save();と書いて表示させていましたが、 よく考えてみるとこれもコンソールを使えば簡単に検証できるということに気がつきました。

 他にもモデルから返ってくる配列ってどんなんだっけ?だとか、こういう条件指定したら何が返ってくるのかなーって時に使ったりしてます。

テーブルにテストデータを挿入

   コンソール上でモデルのインスタンスを取得し、保存すれば実際のテーブルにレコードが挿入されます。 当たり前のことですが、この使い方を知らなかった私はテストデータを挿入するためだけのアクションをわざわざ作っていました。

 他にもレコード挿入時のバリデーションが正しく動作しているかの確認にも使えます。←テスト書け


 パッと思いついたのはこれぐらいですが、要するに言語仕様の確認です。

 まだまだweb開発初心者ですが上記のような当たり前のことを出来るようにし、開発効率を上げられるようになれたらと思います。