八葉の日記

日々、感じたことをまとめる場として利用する

Ruby gem インストール場所確認

gem environmentを使うとでてくる。
INSTALLATION DIRECTORY:~~

VSCodeRubyデバッグする方法で調べてた
VSCodeでRubyコードのデバッグができる環境を構築する(2017年2月現在) - 土屋つかさのテクノロジーは今か無しか

Modern C++ enumにはスコープが設定できる

職場がC++11/14に対応してきたのですが、今までなんちゃってModern C++だったので復習を兼ねてメモ。

Effective Modern C++ ―C++11/14プログラムを進化させる42項目

Effective Modern C++ ―C++11/14プログラムを進化させる42項目

項目10:enumにはスコープを設ける

enum class Color { black, red, blue}; // C++11からはclassを付けるとスコープを限定できる

auto black = false;
//OK. C++98であるようにenum ColorだとNGになる
//enumの中の値が実質グローバル変数のようになる
//過去は対策として、enum Color = {color_black, ....}のようなことをしていた。

if (red < 10.2) //NG. 暗黙の型変換はできない
{
//
}

//別ヘッダファイルでは前方宣言可能
enum class Color; //前方宣言可能

まとめ:
・スコープを限定する→列挙子がグローバル変数になるのを避ける
・暗黙の型変換が不可になる
・前方宣言が減らせる→コンパイル時のファイル依存が減る

The type signature for ‘factorial’ lacks an accompanying binding

参考書とかで以下のコードをghciで入力しようと、タイトルのようなエラーがでると思います。
うまくいかないときはファイルに書いてロードするといい。
factorial :: Int -> Int
factorial 0 = 1
factorial n = n * factorial(n-1)

ghciで上のコード一行ずつ入力してもエラーがでます。(宣言はあるけど定義がないなど、、、)
だから、上のコードを一旦拡張子.hsのファイルに記述して:lでロードするといいです。

Haskellメモ

■型クラス

Prelude> :t (==)
(==) :: Eq a => a -> a -> Bool

=>の前にあるのが型クラス制約というもので、"型aはEq型でないといけない"ことを意味する。
なので、全体では"==は同じ型aの引数をとって、型aをとってBOOLを返す関数です。そして型aはEq型のインスタンスである必要があります"
ということを意味しています。

型クラスの例とサポートしている(しないといけないふるまい)
Eq型:==、/=
Ord型:>、<、>=、<=
Show型:インスタンスを文字列出力可能であること

めも

Humble Object at XUnitPatterns.com


Example: Humble Dialog

Many development environments let us build the user interface
visually by dragging and dropping various visual objects ("widgets")
onto a canvas.
多くの開発環境では、さまざまなビジュアルオブジェクト(「ウィジェット」)を
キャンバスにドラッグアンドドロップすることで、ユーザーインターフェイスを視覚的に
構築できます。

They let us add behavior to these visual objects by selecting one of
the possible actions or events specific to that visual object and typing
logic into the code window the IDE presents us with.
これらのビジュアルオブジェクトには、ビジュアルオブジェクトに固有の可能なアクション
またはイベントの1つを選択し、IDEが提示するコードウィンドウにロジックを入力することによって、
ビジュアルオブジェクトにビヘイビアを追加できます。

This logic may involve invoking the application behind the user interface or it
may involve modifying the state of this or other visual objects.
このロジックは、ユーザインタフェースの背後でアプリケーションを呼び出すことを伴い得るか、
またはこのまたは他の視覚的オブジェクトの状態を変更することを含み得る。

Visual objects are very hard to test efficiently because they are tightly coupled
to the presentation framework that invokes them.
ビジュアルオブジェクトは、それらを呼び出すプレゼンテーションフレームワークに密接に結合されて
いるため、効率的にテストすることは非常に困難です。

The test would need to simulate that environment to provide the visual object with
all the information and facilities it requires.
テストでは、ビジュアルオブジェクトに必要なすべての情報と機能を提供するために、その環境を
シミュレートする必要があります。

This makes testing very complicated, so much so that many development teams don't
bother testing the presentation logic at all.
これはテストを非常に複雑にするので、多くの開発チームはプレゼンテーションロジックのテストを
全く気にしません。

This leads to Production Bugs caused by untested code and Untested Requirements.
これは、テストされていないコードとテストされていない要件によって引き起こされるProduction Bugsに
つながります。

To create the Humble Dialog, we extract all the logic from the view component into
a non-visual component that is testable via synchronous tests.
ハンブルダイアログを作成するために、ビューコンポーネントからロジックのすべてを非同期テストで
テスト可能な非ビジュアルコンポーネントに抽出します。

If this component needs to update the view object's (the Humble Dialog's) state, the Humble Dialog is passed in as an argument.
このコンポーネントがビューオブジェクト(ハンブルダイアログ)の状態を更新する必要がある場合、ハンブルダイアログが引数として渡されます。

When testing the non-visual component, we typically replace the Humble Dialog with a Mock Object that is configured with the indirect input values and the expected behavior (indirect outputs.)
非ビジュアルコンポーネントをテストするときは、通常、間接入力値と予想される動作(間接出力)で構成されたモックオブジェクトをハンブルダイアログに置き換えます。

In some GUI frameworks, where the Humble Dialog has to register itself with the framework for each event it wishes to see, the non-visual component can register itself instead of the Humble Dialog (as long as that doesn't introduce unmanageable dependencies on the context) and this makes the Humble Dialog even simpler because these events go directly to the non-visual component and require no delegation logic
Humble Dialogが見たい各イベントのフレームワークに自分自身を登録しなければならないGUIフレームワークでは、非ビジュアルコンポーネントは、ハンブルダイアログの代わりに自身を登録することができます。コンテキスト)、これらのイベントは非ビジュアルコンポーネントに直接移動し、委譲ロジックを必要としないため、Humble Dialogをさらに単純化します

The following code sample is from a VB view component (.ctl) with some non-trivial logic.
次のコードサンプルは、VBのビューコンポーネント(.ctl)のロジックです。

It is part of a custom plug-in we built for Mercury Interactive's TestDirector tool.
Mercury InteractiveのTestDirectorツール用に作成したカスタムプラグインの一部です。

///////////////////////////////////////////////////////////////////////////////
' Interface method, TestDirector will call this method
' to display the results.Public Sub ShowResultEx(TestSetKey As TdTestSetKey, _ TSTestKey As TdTestKey, _
ResultKey As TdResultKey)
Dim RpbFiles As OcsRpbFiles
Set RpbFiles = getTestResultFileNames(ResultKey)
ResultsFileName = RpbFiles.ActualResultFileName
ShowFileInBrowser ResultsFileName
End Sub

Function getTestResultFileNames(ResultKey As Variant) _ As OcsRpbFiles
On Error GoTo Error
Dim Attachments As Collection
Dim thisTest As Run
Dim RpbFiles As New OcsRpbFiles
Call EnsureConnectedToTd
Set Attachments = testManager.GetAllAttachmentsOfRunTest(ResultKey)
Call RpbFiles.LoadFromCollection(Attachments, "RunTest")
Set getTestResultFileNames = RpbFiles
Exit Function
Error: ' do something ...End Function
Example VbViewWithLogic embedded from VB6/HumbleDialog-Not/ResultViewerPane.ctl
///////////////////////////////////////////////////////////////////////////////

=========================================================
Ideally, we would like to test the logic but we are unable to construct the objects passed in as parameters because they don't have public constructors.
理想的には、ロジックをテストしたいのですが、パブリックコンストラクタを持たないため、渡されたオブジェクトをパラメータとして構築することはできません。

Passing in objects of some other type isn't possible either because the types of the function parameters are hard-coded to be specific concrete classes.
関数のパラメータの型が特定の具象クラスにハードコードされているため、他の型のオブジェクトを渡すことはできません。

We can do an Extract Testable Component (page X) refactoring on the executable to create the testable component leaving behind just the Humble Dialog as an empty shell.
テスト可能なコンポーネントを作成して空のシェルとしてHumble Dialogだけを残すように、実行可能ファイルに対してTestable Component(page X)のリファクタリングを行うことができます。

This typically involves doing several Extract Method refactorings (already done in the original example to make the refactoring easier to understand), one for each chunk of logic that we want to move.
これには、通常、リファクタリングを理解しやすくするために元の例で行っていたいくつかの抽出メソッドリファクタリングを実行します。これは、移動するロジックの各チャンクに対して1つです。

We then do an Extract Class refactoring to create our new testable component class.
その後、Extract Classリファクタリングを実行して、新しいテスト可能コンポーネントクラスを作成します。
The Extract Class refactoring may include both Move Method[Fowler] refactorings and Move Field[Fowler] refactoring to move the logic and the data it requires from the Humble Dialog to the new testable component.
エクストラクトクラスリファクタリングには、Moveメソッド[Fowler]リファクタリングとMove Field [Fowler]リファクタリングの両方が含まれており、必要なロジックとデータをハンブルダイアログから新しいテスト可能コンポーネントに移動できます。
Here's the same view converted to a Humble Dialog:
ここでは、同じビューをハンブルダイアログに変換します:

///////////////////////////////////////////////////////////////////////////////
' Interface method, TestDirector will call this method
' to display the results.Public Sub ShowResultEx(TestSetKey As TdTestSetKey, _ TSTestKey As TdTestKey, _
ResultKey As TdResultKey)
Dim RpbFiles As OcsRpbFiles
Call EnsureImplExists
Set RpbFiles = Implementation.getTestResultFileNames(ResultKey)
ResultsFileName = RpbFiles.ActualResultFileName
ShowFileInBrowser ResultsFileName
End Sub

Private Sub EnsureImplExists() If Implementation Is Nothing Then Set Implementation = New OcsScriptViewerImpl
End If
End Sub
Example VbViewAsHumbleDialog embedded from VB6/HumbleDialog/ResultViewerPane.ctl
///////////////////////////////////////////////////////////////////////////////

以下は、ハンブルオブジェクトが呼び出すテスト可能なコンポーネントOcsScriptViewerImplです:
///////////////////////////////////////////////////////////////////////////////
' ResultViewer Implemenation:
Public Function getTestResultFileNames(ResultKey As Variant) _ As OcsRpbFiles
On Error GoTo Error

Dim Attachments As Collection
Dim thisTest As Run
Dim RpbFiles As New OcsRpbFiles
Call EnsureConnectedToTd
Set Attachments = testManager.GetAllAttachmentsOfRunTest(ResultKey)
Call RpbFiles.LoadFromCollection(Attachments, "RunTest")
Set getTestResultFileNames = RpbFiles
Exit Function
Error: ' do something ...End Function
///////////////////////////////////////////////////////////////////////////////

We could now instantiate this OcsScriptViewerImpl class easily and write VbUnit tests for it.
I've omitted the tests for space reasons because they don't really show anything particularly interesting.
このOcsScriptViewerImplクラスを簡単にインスタンス化し、VbUnitテストを作成することができます。私はスペースの理由でテストを省略しました。なぜなら、特に面白いことは何も実際に表示していないからです。

Humble Object

Humble Object at XUnitPatterns.com
非同期プログラミング - 非同期コードの単体テスト: テストを容易にする 3 つの解決策


Humble Object はインスタンス化することが難しいオブジェクトを、効率的にテストするための考え方です。(詳細は上記リンクを参照デス)
例えば、
・ビジュアルコンポーネントウィジェット、ダイアログなど)があるフレームワーク上にある場合です。
 この時はUnitTestのためには、フレームワークで依存している全オブジェクトをUnitTest環境で構築する必要があります
・非同期に実行されるためテストが難しいアクティブオブジェクトです。
 ※アクティブオブジェクト:スレッド、プロセス、ウェブサーバなどのタスクの基点(エントリーポイント)となる関数を所有するクラスのオブジェクト

使い方
①すべてのロジックをテスト対象のコンポーネントから同期テストを介してテスト可能なコンポーネントに抽出します。
②①のコンポーネントは、テストが難しいコンポーネントのロジックを、動機かつパブリックで呼び出しできるサービスインターフェイスを実装します。
③その結果、Humble Object トコンポーネントは非常に薄いアダプタレイヤーになり、コードはほとんど含まれません。
④ハンブルオブジェクトがフレームワークによって呼び出されるたびに、それはテスト可能なコンポーネントに委譲されます。

例えば、アクティブオブジェクトRequestHandlerThread が初期化されることをテストしようとする場合、
下記をターゲットにして、runして数秒後にinitializedSuccessfullyがtrueを返すことを確認するようなコードを書くのですが、
processOneRequest内部に複雑な処理があって、initializedSuccessfullyの結果が設定される場合は安定したUnitTestを書くことができない。
(実際に数秒まったり、フレームワークの状態によってはエラーとなる)

public class RequestHandlerThread extends Thread {
   private boolean _initializationCompleted = false;
   private int _numberOfRequests = 0;
  
   public void run()  {
      initializeThread();
      processRequestsForever();
   }
  
   public boolean initializedSuccessfully() {
      return _initializationCompleted;
   }
  
   void processRequestsForever() {
      Request request = nextMessage();
      do {
         Response response = processOneRequest(request);
         if (response != null) {
            putMsgOntoOutputQueue(response);
         }
         request = nextMessage();
      } while (request != null);
   }
}

この例では簡単であるが、ストラテジーパターンを使用して、requestHandlerに処理を移譲している。
こうすると、requestHandlerを同期で試験する、スレッドに対しては処理が移譲できていることを確認すればOKとなる。

public class HumbleRequestHandlerThread extends Thread
implements Runnable {
   public RequestHandler requestHandler;
  
   public HumbleRequestHandlerThread() {
      super();
      requestHandler = new RequestHandlerImpl();
   }
  
   public void run() {
      requestHandler.initializeThread();
      processRequestsForever();
   }
  
   public boolean initializedSuccessfully() {
      return requestHandler.initializedSuccessfully();
   }
  
   public void processRequestsForever() {
      Request request = nextMessage();
      do {
         Response response = requestHandler.processOneRequest(request);
         if (response != null) {
            putMsgOntoOutputQueue(response);
         }
         request = nextMessage();
      } while (request != null);
   }



コードは参考ページから持ってきています。
英語自信ないため解釈誤りありましたらごめんなさい^^

負の継承への対応(2)

負の継承への対応を具体的にまとめていく
まず、共通性を侵すことなく可変性を扱う場合は、とくに問題なくあつかえるという前提です。
また、負の可変性は正の可変性と対応した技術で実現します。例えば、正の可変性をテンプレートで
実現した場合は、負の可変性はテンプレートの特殊化になります。

負の可変性を扱うメカニズム
・テンプレートの特殊化
共通の形:型によらず共通

template < class  T>
class Stack{
    StackRep<T> *rep;
}

template < class  T>
class StackRep{
    StackRep<T> *next;
    T* rep
}

上記では、ポインタを持った構造体で管理しているが、整数型に対しては性能要件から動的配列はとれず、
素数も決まっている場合があった場合は、テンプレートの特殊化で以下のようにできる。

template < >
class Stack<int>{
    static int rep[10000];
}

・デフォルト引数
アルゴリズムに強い共通性がある場合で、値に対して弱いバリエーションがあった場合、
(言い換えると、十中八九はこの値だけど、ごくまれにコレというようなケース)

・データのキャンセル

//テキストバッファを扱うクラス
template <class CharSet >
class TextBuffer{
public:
    Line<CharSet> getLine(const LineNumber&);

private:
   
   LineNumber firstLine, lastLine;
   int currentLine;
   //はじめと最後の行、現在の行を扱えるとメンバ変数がいる
}

1行だけ扱うテキストバッファが必要で、テキストバッファに対する機能を有している上記を継承する場合は、
複数行扱うメンバーは邪魔になる。

//ページ単位でテキストバッファを扱う
template <class CharSet >
class PageBuffer : TextBuffer<CharSet>{
public:
} 

//1行単位でテキストバッファを扱う
template <class CharSet >
class LineBuffer : TextBuffer<CharSet>{
public:
} 

派生クラスで、基底クラスのメンバをキャンセルすることはできないため、可変性を外側にくくりだす。
ここでは、ページ単位でテキストバッファを扱うクラスと1行単位で扱うテキストバッファを以下のように定義する。

//まず、それぞれの実装を定義
template <class CharSet >
class PageBufferRep : public TextBufferRep<CharSet>{

   LineNumber firstLine, lastLine;
   int currentLine;
} 

template <class CharSet >
class LineBufferRep  : public TextBufferRep<CharSet> {
public:
} 

上記の実装に対して、クライアントへ提供するハンドルを以下のように定義する。

template <class CharSet >
class TextBuffer{
public:
    Line<CharSet> getLine(const LineNumber&);

protected:
   TexstBufferRep<CharSet>* rep;//最初の例と比較すると、所持していたデータメンバが抽象化されている。
   TextBuffer(TexstBufferRep<CharSet>*); //コンストラクタでRepを割り当てる
}

最終的にはこうする。

template <class CharSet >
class PageBufferBuffer : public TextBuffer<CharSet>{
public:
    PageBufferBuffer () 
     : TextBuffer<CharSet>(new PagedTextBufferRep){}
}
template <class CharSet >
class LineBufferBuffer : public TextBuffer<CharSet>{
public:
    LineBufferBuffer () 
     : TextBuffer<CharSet>(new LineBufferRep  ){}
}

図でいうと、
f:id:konboi_kun:20180225194822j:plain
以下になってます
f:id:konboi_kun:20180225200250j:plain


つかれたので、あとで整理しよう