ちくわとチワワはよく似てる

ちくわのちくわによるちくわのためのアレ。
  • rss
  • archive
  • 「アジャイルがダメだと思う7つの理由」が間違っている97の理由

    arclamp 鈴木さんの「アジャイルがダメだと思う7つの理由」を読んでの感想と反論を。

    1.全体スケジュールにコミットできない

    アジャイルはタイムボックス型(一定期間で棚卸しをして、それを繰り返す)のマネジメントをする。だから、全体としての計画は立てられない。「だって、最初に全ての機能を洗い出せないでしょ」というのは分かる、分かるけど全体の計画は立てないといけない。経営者は顧客やVCと全体の計画にコミットしなきゃいけないんだ。そのときに「やってみなきゃ分からない」なんて言えるわけでない。

    アジャイル開発でも全体スケジュールにコミットすることは可能です。スケジュールが遅れだしたら鈴木さんがお金を追加投入して開発メンバーを増やせばいい。(あまりおすすめできない悪手だけど。優先度の低い機能を開発スコープから落とすか、期間を延ばす方がより理想的な手段だと思う。短い期間であれば残業を増やすとかでもいいでしょう)

    今までは一括請負契約で開発会社だけに負わせていたリスクを、発注側も負う必要が出てきただけなんじゃないかなあ。

    2.アーキテクチャ上の無駄が生じる

    ソフトウェアの構造や構成は工程が進むほどに修正しにくくなり、ずっと残る。だから、アーキテクチャ設計は慎重に全体を考えながらやらなきゃいけない。でも、アジャイルだから全体が決まらないとか言って、なんとなく流行の技術を使って作ってないか?そうやって作られた物は負債になる。

    たとえばtwitterはRuby On Raisで初期構築したシステムをScalaに置き換えた。その無駄を超えるだけの成功が見えているからいいさ。でも、大抵の場合はそうじゃない。近視眼的なアーキテクチャが足かせとなり、生産性が落ちて、エンジニアのモチベーションを下げる。

    もちろん、うまくアーキテクチャを組めているアジャイルチームだってある。でも、それはメンバーに優秀なアーキテクトがいただけのことでしょ。プロセスがどうあれ、アーキテクチャはちゃんと考えるべきなんだ。

    開発を始める前にアーキテクチャを決めるのはアジャイル開発でも一般的に行われていると思います。ただし、そのアーキテクチャが正しくなかった時に備えて事前アーキテクチャ設計は必要最低限であるべきです。

    4.変化ヲ抱擁スルために固定化している

    変化に適応するというのは全ての開発チームが取り組むべき課題だ。

    現在のソフトウェア工学は不十分なので構造的に柔軟性を得ることはとても難しい。テーブル構成をがしがし変えてもコードが付いてくれば良いけど、そんなことはできないから、アジャイルはプロセスを柔軟にして変化に適応すると考えた。これは悪くないアイデアだ。

    でも、完璧じゃない。大抵の場合は要員を固定化するという前提が付くのです。ロールベースでないとノウハウが人に貯まり、どんどん引き離せなくなる。そして、同じ事を繰り返すメンバーはモチベーションが下がり、いつか辞めることになるのだ。

    要員の固定化はまあ困りますよね。 弊社では、開発メンバーを少しずつ入れ替えることで要員の固定化に対応しており、うまく回っているように見えます。なので、要員の固定化をもってアジャイルがダメだというのには同意できません。

    7つの理由のうちの3, 5, 6, 7はアジャイル開発とあまり関係ないので割愛しますね。

    今回の鈴木さんのエントリは、あるアジャイル開発の現場でのアーキテクトという立場からのアジャイルに対して抱いた印象として興味深く読ませていただきました。

    開発側へリスクを負わせようとした発注側とそれに対してディフェンシブになってしまった開発側、というよく見かける構図になってしまったのが敗因なのかなあ。

    • 2 months ago
    • 3 notes
  • iOSアプリからOpenCVを使ってみる

    事前準備

    インストールに必要なので事前にcmakeをインストールしておく。

    brew install cmake
    

    シンボリックリンクを張って /Developer 経由でヘッダファイルなどを参照できるようにする。

    cd /
    sudo ln -s /Applications/Xcode.app/Contents/Developer
    

    OpenCVフレームワークをビルド

    以下の手順でOpenCVフレームワークをビルドする。masterブランチだとビルドに失敗したので、2.4ブランチでビルドを行った。

    cd ~/src
    git clone https://github.com/Itseez/opencv.git
    cd opencv/
    git checkout 2.4
    cd ..
    python opencv/ios/build_framework.py ios
    

    プロジェクトへOpenCVフレームワークを追加

    新規のiOSプロジェクトを作成し、そこへ先ほどビルドしたOpenCVフレームワークを追加する。

    まずは新規のiOSプロジェクトを作成し、画面左のプロジェクトナビゲータの「Frameworks」を右クリックし、「Add Files to “プロジェクト名”…」を選択し、~/src/ios/opencv2.framework を選んで「Add」ボタンを押す。

    次に、${プロジェクト名}-Prefix.pch へ以下のコードを追加。

    #ifdef __cplusplus
    #import <opencv2/opencv.hpp>
    #endif
    

    Objective-CとC++を混在させる

    OpenCVの処理はC++で記述する必要があるので、OpenCVの処理を行うソースファイルの拡張子を「&ast;.m」から「&ast;.mm」へ変更しておく。

    サンプルコード

    OpenCVによる画像編集のサンプルとして、カラーの画像をモノクロにしてみる。

    UIImageとMatの相互変換

    OpenCVで画像を操作するには事前にUIImageオブジェクトをMatオブジェクトへ変換する必要がある。

    まずは、UIImageとMatを相互変換するcvMatFromUIImage:メソッドとUIImageFromCVMat:メソッドをViewController.mmへ定義する。

    - (cv::Mat)cvMatFromUIImage:(UIImage *)image
    {
      CGColorSpaceRef colorSpace = CGImageGetColorSpace(image.CGImage);
      CGFloat cols = image.size.width;
      CGFloat rows = image.size.height;
    
      cv::Mat cvMat(rows, cols, CV_8UC4); // 8 bits per component, 4 channels
    
      CGContextRef contextRef = CGBitmapContextCreate(cvMat.data,                 // Pointer to  data
                                                     cols,                       // Width of bitmap
                                                     rows,                       // Height of bitmap
                                                     8,                          // Bits per component
                                                     cvMat.step[0],              // Bytes per row
                                                     colorSpace,                 // Colorspace
                                                     kCGImageAlphaNoneSkipLast |
                                                     kCGBitmapByteOrderDefault); // Bitmap info flags
    
      CGContextDrawImage(contextRef, CGRectMake(0, 0, cols, rows), image.CGImage);
      CGContextRelease(contextRef);
      CGColorSpaceRelease(colorSpace);
    
      return cvMat;
    }
    
    -(UIImage *)UIImageFromCVMat:(cv::Mat)cvMat
    {
      NSData *data = [NSData dataWithBytes:cvMat.data length:cvMat.elemSize()*cvMat.total()];
      CGColorSpaceRef colorSpace;
    
      if (cvMat.elemSize() == 1) {
          colorSpace = CGColorSpaceCreateDeviceGray();
      } else {
          colorSpace = CGColorSpaceCreateDeviceRGB();
      }
    
      CGDataProviderRef provider = CGDataProviderCreateWithCFData((__bridge CFDataRef)data);
    
      // Creating CGImage from cv::Mat
      CGImageRef imageRef = CGImageCreate(cvMat.cols,                                 //width
                                         cvMat.rows,                                 //height
                                         8,                                          //bits per component
                                         8 * cvMat.elemSize(),                       //bits per pixel
                                         cvMat.step[0],                            //bytesPerRow
                                         colorSpace,                                 //colorspace
                                         kCGImageAlphaNone|kCGBitmapByteOrderDefault,// bitmap info
                                         provider,                                   //CGDataProviderRef
                                         NULL,                                       //decode
                                         false,                                      //should interpolate
                                         kCGRenderingIntentDefault                   //intent
                                         );
    
    
      // Getting UIImage from CGImage
      UIImage *finalImage = [UIImage imageWithCGImage:imageRef];
      CGImageRelease(imageRef);
      CGDataProviderRelease(provider);
      CGColorSpaceRelease(colorSpace);
    
      return finalImage;
     }
    

    モノクロにしてみる

    写真をモノクロにしてみる。

    - (IBAction)doDidPress:(id)sender {
        UIImage *image = [UIImage imageNamed:@"neko_tsubaki_blue_car.jpg"];
    
        // 写真をモノクロにする
        cv::Mat srcMat = [self cvMatFromUIImage:image];
        cv::Mat greyMat;
        cv::cvtColor(srcMat, greyMat, CV_BGR2GRAY);
        UIImage *greyImage = [self UIImageFromCVMat:greyMat];
    
        self.imageView.image = greyImage;
    }
    

    こんな感じ。

    参考

    • 「Instalation in iOS」
      • http://docs.opencv.org/trunk/doc/tutorials/introduction/ios_install/ios_install.html#ios-installation
    • 「OpenCV iOS Hello」
      • http://docs.opencv.org/trunk/doc/tutorials/ios/hello/hello.html#opencvioshelloworld
    • 「OpenCV iOS - Image Processing」
      • http://docs.opencv.org/trunk/doc/tutorials/ios/image_manipulation/image_manipulation.html
    • 3 months ago
    • 1 notes
  • yfa29212:

(2月22日(金曜日)から)

    yfa29212:

    (2月22日(金曜日)から)

    (via haru012)

    Source: railman.cocolog-nifty.com
    • 3 months ago
    • 259 notes
  • “一般的には2値化のことを「モノクローム化」と考えるが(私もそうだった)実際にはモノクローム化した画像はいわゆる「グレイスケール」画像であり黒と白以外の色が含まれる。”
    — http://kazzz.hatenablog.com/category/OpenCV?page=1347894000
    • 3 months ago
  • zshでワード単位の前後移動

    これまでは、ワード単位での前後移動がきっとあるんだろうなあと思いながらもチマチマとCtrl-fとCtrl-bで前後移動してたんだけど、スリーアウトどころかサウザンドアウトぐらいになったのでいい加減調べた。

    • ひとつ先のワードへ移動 (forward-word)
      • ESC f
    • ひとつ前のワードへ移動 (backward-word)
      • ESC b

    ワード単位での移動は「forward-word」と「backward-word」でそれぞれ「ESC f」と「ESC b」に割り当てられているみたい。Macだとoption fとoption-bでも行けるんだけど我が家のoptionキーはずいぶんと押しづらい所にあるので「Ctrl + ]」と「Ctrl + [」に設定することにする。(MacじゃなければAlt-fとAlt-bで行けたんだけどなあ)

    ということで.zshrcに以下を追記。bindkey -e などの後ろに置かないといけないので注意すること。

    # Ctrl + o、Ctrl + i でワード単位で前後に移動
    # ^[ で始まる他のキーバインドがあると動作がひっかかるようになるので
    # 事前にすべて削除しておく
    bindkey -rp "^["
    bindkey "^[" backward-word
    bindkey "^]" forward-word
    
    • 7 months ago
    • #zsh
    • #unix
    • #macosx
  • EclipseでEmacs風のキーバインド

    何年かぶりにEclipseを使っているのだけど、生のキーバインドがアレすぎるので以下の設定を施してEmacs風のキーバインドにしたった。

    Eclipseの設定画面から「General - Keys」を選択して以下をセットする。

    Line Start:     ⌃A
    Line End:     ⌃E
    Previous Column:     ⌃B
    Next Column:     ⌃F
    Join Lines:     ⌃J
    Delete to End of Line:     ⌃K
    Line Down:     ⌃N
    Line Up:     ⌃P
    Delete Previous Word:     ⌃W
    Delete Next:     ⌃D
    Delete Previous:     ⌃H
    
    • 11 months ago
  • 『マックの唄』

    ♪ 銀のマックに 唇よせて
      だまって見ている 虹色のグルグル
      マックは何にも 言わないけれど
      マックの気持ちは よく分かる
      マック可愛いや 可愛いやマック
    

    • 1 year ago
  • kamblr: 乾いた雑巾を絞る技術

    kamblr:

    未踏事業の増井PM・首藤PM合同合宿で講演させていただきました。
    以下はその時の発表資料です(PDF版)。

    スライドの後半(25ページ目)以降が本題で、以下のようなことについて話しました。

    • 「未踏」なソフトを作るにはどうしたらよいか?
    • 「思索」の重要性と、その方法論
    • 脳や心理を意識した手法

    …

    Source: kamblr
    • 1 year ago
    • 8 notes
  • goryugo:

johnnys:

sft:


monta:

Kalimpong, Blue hour (via Davideo1)

    goryugo:

    johnnys:

    sft:

    monta:

    Kalimpong, Blue hour (via Davideo1)

    Source: monta
    • 1 year ago
    • 74 notes
  • “

    日本でITというのは、「今ある仕事をコンピュータシステムに乗せること」だ。私はそれを商売にしているから余計実感するが、そんなことをしても何も変わらない。便利になることと余計面倒になることが半々でトータルでは大して変わりがない。

    ITが本当に力を発揮するのは、「先にコンピュータシステムを作って、その回りに人を配置して仕事にする」時だ。コンビニチェーンもDELLもアマゾンもそういうやり方でITを使っている。

    そういう使い方をするとITは本当に力を発揮する。日本がこれから競争していくのは、そういうタイプのITだ。身の回りにある「なんちゃってIT」でこれを判断してはいけないと思う。

    ”
    — 原油高と同じくらい深刻な「ホワイトカラーの仕事破壊」 - アンカテ (via otsune)
    Source: otsune
    • 1 year ago
    • 509 notes
  • GCDのディスパッチキューを使ってみる

    先日はNSOperationQueueを使って非同期処理を行ったけど、今回はGCDのディスパッチキューを使って非同期処理を行ってみる。

    まずはディスパッチキューを取得し、

    // ディスパッチキューを取得
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    

    取得したディスパッチキューと非同期にしたい処理をブロックにしたものを引数にdispatch_async関数を呼び出す。

    // 非同期処理を呼び出す
    dispatch_async(queue, ^{
        NSLog(@"=> Operate!!");
    });
    

    これだけで非同期に処理を呼び出すことができます。

    // ディスパッチキューを取得
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    // 非同期処理を呼び出す
    dispatch_async(queue, ^{
        NSLog(@"=> Operate!!");
    });
    
    • 1 year ago
    • #iOS
    • #Objective-C
  • 非同期に処理を呼び出したい

    iOSアプリケーションで非同期に処理を行うためにはオペレーションキューを利用します。

    ファイルのダウンロードのような完了するまでに時間のかかる処理をメインスレッドで実行してしまうと、処理が完了するまで画面が固まってしまいユーザビリティがが著しく低下してしまいます。これを避けるため、完了までに時間のかかる処理はメインスレッドとは別のスレッドを作成して非同期に処理を行う必要があります。iOSにはいくつかの非同期処理を行う方法がありますが、ここではオペレーションキューを使った方法を解説します。

    オペレーションキューを用いた非同期処理

    非同期に処理を行うためには、非同期に行いたい処理をオペレーション(NSOperation)として定義し、そのオペレーションをオペレーションキュー(NSOperationQueue)へ追加してやります。追加されたオペレーションはオペレーションキューにより直ちに別スレッドで実行されます。

    以下はオペレーションキューのサンプルです。ブロックを用いてNSOperationのサブクラスであるNSBlockOperationを生成し、それをNSOperationQueueへと追加することで非同期処理を呼び出しています。

    // オペレーションキューを作成
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    // オペレーションを作成
    // (NSBlockOperationはNSOperationのサブクラス)
    NSOperation *operation = [NSBlockOperation blockOperationWithBlock:^{
        NSLog(@"=> Operate!!");
    }];
    
    // オペレーションをオペレーションキューへ追加
    [queue addOperation:operation];
    
    // オペレーションキューをリリース
    [queue release];
    

    NSOperationQueueのaddOperationWithBlock:メソッドを使うことでもう少し短く書くことができます。

    // オペレーションキューを作成
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    // オペレーションとなるブロックをオペレーションキューへ追加
    [queue addOperationWithBlock:^{
        NSLog(@"=> Operate Again!!");       
    }];
    
    // オペレーションキューをリリース
    [queue release];
    

    メインスレッドとオペレーションキュー

    UIの更新処理等メインスレッドから呼び出す必要のあるメソッドをバックグラウンドのスレッドから呼びたい場合は、NSOperationQueueクラスのmainQueueメソッドを呼ぶことでメインスレッドに対応づけられたオペレーションキューを取得します。

    次のサンプルでは画面上のテキストフィールドの更新を行うためにメインキューを利用しています。

    // オペレーションキューを作成
    NSOperationQueue *queue = [[NSOperationQueue alloc] init];
    
    [queue addOperationWithBlock:^{
        // ウェブページを取得し...
        NSURL *url = [NSURL URLWithString:@"http://example.com/"];
        NSString *response = [NSString stringWithContentsOfURL:url
                                                      encoding:NSUTF8StringEncoding
                                                         error:nil];
        // 取得したデータを画面へ表示
        // (UIの更新はメインスレッドから行う必要がある)
        [[NSOperationQueue mainQueue] addOperationWithBlock:^{
            self.textView.text = response;           
        }];
    }];
    
    // オペレーションキューをリリース
    [queue release];
    

    参考サイト

    • 並列プログラミングガイド — https://developer.apple.com/jp/devcenter/ios/library/documentation/ConcurrencyProgrammingGuide.pdf
    • 1 year ago
    • #iOS
    • #Objective-C
  • UIScrollViewでTumblrっぽいビューアをつくる

    UIScrollViewの使い方がよく分かってなかったので、練習がてらにこんな感じの画像ビューアをUIScrollViewで作ってみた。

    まずはUIScrollViewのコンテント領域をセットする。viewDidLoadメソッドなどでUIScrollViewのcontentSizeに適当な値をセットする。今回のサンプルでは320x320の写真を5枚分貼りたかったので、コンテント領域は幅320x高さ1600とした。

    - (void)viewDidLoad
    {
        ...
        // スクロールビューのcontentSizeの高さを画像5つ分の高さにする
        self.scrollView.contentSize = CGSizeMake(320, 320 * 5);
        ...
    }
    

    次はURLより画像を読込み、読み込んだ画像をUIImageViewへセットしてUIScrollViewへaddSubview:する。これもviewDidLoadで処理を行う。

    画像のダウンロードをメインスレッド上で行うと画面が固まってしまうため、ダウンロード処理がバックグランドで行う。逆にUIの更新処理メインスレッドから呼ばれる必要があるため、UIScrollViewへのUIImageViewの追加はメインスレッドで行う。

    NSURL *url = [NSURL URLWithString:[_imageUrls objectAtIndex:i]];
    
    // 非同期に画像をロードする
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSData *data = [NSData dataWithContentsOfURL:url];
    
        // UIの更新はメインスレッドで行う必要がある
        dispatch_async(dispatch_get_main_queue(), ^{
            UIImageView *view = [[UIImageView alloc] initWithFrame:CGRectMake(0, i * 320, 320, 320)];
            view.image = [UIImage imageWithData:data];
            [self.scrollView addSubview:view];
        });
    });
    

    大まか流れはこんな感じ。UIScrollViewはすごく面倒な印象があったんだけど、今回行った作業は実質contentSizeに値をセットするだけと以外と簡単に使えたのでUIScrollViewへの親近感がすこし高まりました。

    以下サンプルコード。

    @implementation ViewController {
        NSArray *_imageUrls;
    }
    
    @synthesize scrollView = _scrollView;
    
    - (void)clearImages
    {
        for (id view in self.scrollView.subviews) {
            [view removeFromSuperview];
        }    
    }
    
    - (IBAction)loadImages
    {
        [self clearImages];
    
        for (int i = 0; i < _imageUrls.count; i++) {
            NSURL *url = [NSURL URLWithString:[_imageUrls objectAtIndex:i]];
    
            // 非同期に画像をロードする
            dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
                NSData *data = [NSData dataWithContentsOfURL:url];
    
                // UIの更新はメインスレッドで行う必要がある
                dispatch_async(dispatch_get_main_queue(), ^{
                    UIImageView *view = [[UIImageView alloc] initWithFrame:CGRectMake(0, i * 320, 320, 320)];
                    view.image = [UIImage imageWithData:data];
                    [self.scrollView addSubview:view];
                });
            });
        }   
    }
    
    - (void)viewDidLoad
    {
        [super viewDidLoad];
    
        if (!_imageUrls) {
            // 画像URLを初期化
            _imageUrls = [[NSArray alloc] initWithObjects:
                          @"http://distilleryimage4.s3.amazonaws.com/a0d2941e6bd611e181bd12313817987b_7.jpg",
                          @"http://distilleryimage8.s3.amazonaws.com/f1f2e06260d511e19896123138142014_7.jpg",
                          @"http://distilleryimage4.s3.amazonaws.com/b7611c7e5e1a11e19e4a12313813ffc0_7.jpg",
                          @"http://distilleryimage1.s3.amazonaws.com/8fcfda5a610911e1b9f1123138140926_7.jpg",
                          @"http://distilleryimage5.s3.amazonaws.com/2821cf2e60ed11e19e4a12313813ffc0_7.jpg",
                          nil];
        }
    
        // スクロールビューのcontentSizeの高さを画像5つ分の高さにする
        self.scrollView.contentSize = CGSizeMake(320, 320 * 5);
    
        // _imageUrlsをロード
        [self loadImages];
    }
    ...
    
    • 1 year ago
    • 1 notes
    • #iOS
    • #Objective-C
  • for文の書き方を忘れてた…

    こんなんでした。すっかり忘れてた。

    for (id view in subviews) {
        [view removeFromSuperview];
    }
    
    • 1 year ago
  • 指定したURLから画像をダウンロードしてUITableViewに表示する

    こんな感じで。NSDataの形式でダウンロードしてからUIImageに変換するする。

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    
        // 画像はきめうち
        NSURL *url = [NSURL URLWithString:@"http://img.yubin-nenga.jp/sozai/img/jp12t_et_0255.png"];
        NSData *data = [NSData dataWithContentsOfURL:url];
        UIImage *image = [UIImage imageWithData:data];
        cell.imageView.image = image;
    
        return cell;
    }
    
    • 1 year ago
© 2007–2013 ちくわとチワワはよく似てる
Next page
  • Page 1 / 355