フレームとライブラリの違い

まえがき



現代の開発者が効率を高めようとしているのは秘密ではなく、支援するためにライブラリとフレームワークを要求しています。







フレームワーク(caracas)という言葉は非常にありふれたものになっているので、混乱が生じ始めています-フレームワークと呼ばれるものとそうでないもの







この作業は、ライブラリのフレームの機能、違いを明確にすることを目的としています。 フレームにはライブラリが付属しているため、フレームやライブラリが目の前にあるものを判別するのが一般に難しい場合があります。







図書館



ライブラリはシンプルです。 誰かがコードを書き、公開メソッド/プロパティ(API)を公開し、これを使用できます。 ある意味では、ライブラリはサービスであり、コードはクライアントです。







ライブラリは、アプリケーションのビルド方法に制限を課しません。 ライブラリを使用するためのルールに従う必要があるだけです-APIに従ってください。







ライブラリは、アプリケーションの構築(コーディング)の段階である実装レベルで制限を課していると結論付けています。







例として、名と姓を操作するための架空のJavaScriptライブラリのフラグメントを示します。







var nameUtil = { correctFullName:function(fullname){ var f = fullname.replace(/^ +| +$| {2}/g, "") f = f.substring(0,1).toUpperCase()+f.substring(1,f.length) f = f.substring(0, f.indexOf(" ")+1) + (f.substring(f.indexOf(" ")+1, f.indexOf(" ")+2)).toUpperCase() + f.substring(f.indexOf(" ")+2, f.length) return f } }
      
      





「nameUtil.correctFullName」メソッドは、個人のフルネームのスペルを修正します。つまり、「John leaf」は「John Leaf」でそれを修正します。 このライブラリをプロジェクトに配置し、そのサービスの使用を開始します-そのメソッドを呼び出します。つまり:







 nameUtil.correctFullName(“some Name”)
      
      





フレーム



ワイヤフレームは別の話ですが、ワイヤフレームはアプリケーションレベルのアーキテクチャレベルで制限を課します。 さらに、その影響は実装のレベルにまで及びます。







Wikipediaの記事では、Wolfgang Prieの研究を引用し、凍結スポットとホットスポットについて言及しています。 ソース「メタパターン—再利用可能なオブジェクト指向デザインの要点を捉える手段」では、グレーとホワイトのホットスポットについて説明しています。







次の図でこれを解釈してみましょう。









1-フレームおよびシステムの他の部分







青い点はフレームの一部を示しており、変更されていません。 オレンジ色の点は、プロジェクトの一部として作成された部分です。







ほとんどの場合、ライブラリとフレームワークの次の違いが言及されています。









ワイヤフレームの実用的な例



ワイヤフレームを作成し、ワイヤフレームのプロパティをどのように実現したかを確認してください。 フレームワークは、アーキテクチャテンプレートを実装します。この例では、MVCです。 イベント処理の一環として、デザインテンプレート「Publisher-Subscriber」が適用されました。







フレームワークを使用して、架空のHRアプリケーションの一部を作成します。 このアプリケーションフラグメントでは、経験に基づいてフィルタリングできるテーブルに従業員のリストのみが表示されます。







システムにJavaScript用の次のコンポーネントを作成します。







EventBus-コントローラーインスタンスオブジェクト、イベントバス。 その中で、イベントサブスクライバーを登録し、イベントをポストします。 イベントを配置するとき、バスはイベント署名(識別子)でサブスクライバーを見つけ、イベント処理メソッドを呼び出します。 イベントバスは、システムのすべての部分を接続します。 これはシステム内に1つのコピーで存在するため、JavaScript表記を使用して作成します。







 /* * -,  ,       . */ EventBus = { subscribers:[], /* *    * @param subscriberObject -   * @param subscriberMethod       */ subscribe:function(subscriberObject, subscriberMethod, event) { var subscriber = {} subscriber.object = subscriberObject subscriber.method = subscriberMethod subscriber.event = event this.subscribers[this.subscribers.length]=subscriber }, /* *   * @param eventId -  * @param params  * @param callback ,          * @return      */ publish:function(eventId, params, callback){ for(var i=0; i<this.subscribers.length; i++){ var event = this.subscribers[i].event //console.log("eventId=",eventId, " callback=", typeof callback) if(event===eventId){ if(typeof callback=='function'){ callback(this.subscribers[i].object[this.subscribers[i].method](params)) } else { this.subscribers[i].object[this.subscribers[i].method](params) } } } } }
      
      





テーブル -テーブル形式の情報の視覚表示のコンポーネント。 特定の種類のデータ構造が必要です。 コンストラクターオブジェクトとして実装され、インスタンスを作成できます。







 /* * -,     * @param nameParam    * @param eBus   * @param domId   DOM-    */ function Table(nameParam, eBus, domId){ var name = nameParam var targetDomId = domId var eventBus = eBus /* *   * @param params  ,      */ this.show = function(params){ var data={} data.headers=[] data.rows=[] this.remove() // get data from a data source eventBus.publish(name+ ".getDataSet", params, function(d){ data = d}) var targetDom = document.getElementById(targetDomId) var tableElement = document.createElement("TABLE") var tbodyElement = document.createElement("TBODY") var trElement = document.createElement("TR") trElement.style.background="#eaeaea" for(i=0;i<data.headers.length;i++){ var tdElement = document.createElement("TD") tdElement.appendChild(document.createTextNode(data.headers[i])) trElement.appendChild(tdElement) } tbodyElement.appendChild(trElement) for(i=0;i<data.rows.length;i++){ var trElement = document.createElement("TR") for(j=0;j<data.rows[i].length; j++){ var tdElement = document.createElement("TD") tdElement.appendChild(document.createTextNode(data.rows[i][j])) trElement.appendChild(tdElement) } tbodyElement.appendChild(trElement) } tableElement.appendChild(tbodyElement) targetDom.appendChild(tableElement) tableElement.border=1 } /* *    DOM */ this.remove = function(){ var targetDom = document.getElementById(targetDomId) try{ while (targetDom.firstChild) { targetDom.removeChild(targetDom.firstChild); } }catch(e){} } }
      
      





DataSource-データソース、インスタンスオブジェクト。 彼は特定のデータ構造を与える方法を知っています。 内部には、データ自体のテストセット(データ変数)が含まれています。







 /* * -,   */ DataSource = { /* *    * @return   */ loadDepartments:function(){ return data } } //   var data = [ {name:"IT", employees:[ {name:"Federico", surname:"Gonsales", position:"Engineer", hirenDate:"2013-01-02"}, {name:"Mike", surname:"Saldan", position:"Tester", hirenDate:"2011-11-22"}, {name:"Leo", surname:"Sigh", position:"Architect", hirenDate:"2001-12-12"} ] }, {name:"Sales", employees:[ {name:"Sarah", surname:"Connor", position:"Manager", hirenDate:"2010-04-14"}, {name:"Richard", surname:"Senom", position:"Specialist", hirenDate:"2014-05-07"} ] } ]
      
      





Employeeは、サブジェクト領域のオブジェクトであるEmployeeを表すモデルコンストラクターオブジェクトです。







 function Employee(nameParam, surnameParam, positionParam, hirenDateParam){ var name = nameParam var surname = surnameParam var position = positionParam var hirenDate = hirenDateParam this.setName = function(n){ name=n } this.setSurname = function(s){ surname=s } this.setPosition = function(p){ position=p } this.setHirenDate = function(d){ hirenDate=d } this.getName = function(){ return name } this.getSurname = function(){ return surname } this.getPosition = function(){ return position } this.getHirenDate = function(){ return hirenDate } this.getFullName = function(){ return name+" "+surname } this.getExperience = function(){ var oneDay = 24*60*60*1000; var now = new Date(); //console.log(hirenDate.getTime() +"-"+ now.getTime()) var diffDays = Math.round(Math.abs((hirenDate.getTime() - now.getTime())/(oneDay))) return (diffDays/365).toFixed(0) } }
      
      





部門 -サブジェクトエリアのオブジェクトを表すモデルコンストラクターオブジェクト-部門。







 /* * - ,     * @param nameParam   */ function Department(nameParam){ var name = nameParam var employees = [] this.setName = function(n){ name=n } this.addEmployee = function(e){ employees[employees.length] = e } this.getName = function(){ return name } this.getEmployees = function(){ return employees } }
      
      





Main-アプリケーションのメインオブジェクトであり、すべてを一緒に接続します。 使用に関しては、フレームワークは独自のルールを作成します。 テーブル(テーブル)のページに配置するには、次の手順を実行する必要があります。







ビジュアルコンポーネントによって生成されたイベントハンドラーを指定して、Tableのインスタンスを作成します。

「getDataSet」パラメーターを使用した呼び出しに応答して、イベントハンドラーは次の形式のJSON構造を返す必要があります。

[ヘッダー:[“ first”、“ second”]、行:[[value1、value2]、[value3、value4]]]







「メイン」オブジェクトを見ると、データセットを「テーブル」コンポーネントに送信するためにモデルインスタンスを作成する必要はないように思えるかもしれませんが、そうではありません。 モデルオブジェクトには、たとえば、従業員の勤続期間の計算(メソッド「getExpirience」)など、コントローラー内にあるべきではないビジネスロジックが含まれます。







 /* * -,   ,     , *   ,           Table */ var Main = { /* *    ,    *  ,           */ init:function(){ var myTable = new Table("myTable", EventBus, "employeeTable") EventBus.subscribe(myTable, "show", 'employee.showTable') EventBus.subscribe(this, "getEmployeesDataSet", "myTable.getDataSet") EventBus.subscribe(DataSource, "loadDepartments", "loadDepartments") }, /* *    ,    ,    * @param params     */ getEmployeesDataSet:function(params){ var data EventBus.publish("loadDepartments", null, function(d){ data = d }) var departments = [] for(i=0; i<data.length; i++){ department = new Department(data[i].name) for(j=0;j<data[i].employees.length; j++){ var h = data[i].employees[j].hirenDate var hirenDate = new Date(h.substring(0,4), h.substring(5,7), h.substring(8,10)) employee = new Employee(data[i].employees[j].name, data[i].employees[j].surname, data[i].employees[j].position, hirenDate) department.addEmployee(employee) } departments[i] = department } records = [] var c=0 for(i=0;i<departments.length;i++){ department = departments[i] employees = department.getEmployees() for(j=0;j<employees.length;j++){ if(params){ if(params.expirience){ if(employees[j].getExperience()*1 >= params.expirience*1){ records[c] = [employees[j].getFullName(), employees[j].getPosition(), employees[j].getExperience(), department.getName()] c++ } } }else{ records[c] = [employees[j].getFullName(), employees[j].getPosition(), employees[j].getExperience(), department.getName()] c++ } } } var dataSet={ headers:["Full name", "Position", "Expirience", "Department"], rows:records } return dataSet } }
      
      





図2では、クラスがMVCパターンの一部に属していることを示します。









2-アプリケーションの一部







図3は、メッセージングシーケンスを示しています。









3-シーケンス図







まとめ



条件付きで、「コードセット」を作成済みと呼びます。

「コードのセット」は、ドメインモデルのオブジェクトコンストラクターを作成する義務を負いません。 Main.jsでは、Table.jsのデータソースは何でもかまいません。 これは、フレームワーク、そのアーキテクチャ実装(MVC)には適用されません。 特定のパラメーターを指定してTable.jsメソッドを呼び出すだけです。 これはライブラリプロパティです。







ビジュアルコンポーネントTable.jsを使用する場合、「コードセット」は特定の構造のデータを提供する必要があります。 これはMVC要件ではないため、フレームワークとは関係ありません。 これはライブラリのプロパティです。







「コードセット」により、ビジュアルコンポーネントはイベントバスを介してイベントを送信し、「リスナー」(このイベントのサブスクライバー)が存在するようにします。 ビューをイベント処理、制御から分離します。これは既にMVCの要素です。 これはワイヤーフレームプロパティです。 ワイヤーフレームコード(EventBus.js)がコードを呼び出します。 これはワイヤーフレームプロパティです。







結論



MVCアーキテクチャーからコードを直接使用して、制御コンポーネントとは別に視覚コンポーネントを作成するという要件を実現することができました。 ドメインモデルを作成する義務が失敗しました。 したがって、MVCパターンに従うため、モデルの作成は合意により行われます。







コンポーネントを作成または使用したことに気づいた場合:







a)プロジェクトに建築パターンをもたらす

b)コンポーネントは、実行のキー「スレッド」の制御を転送されます

c)コンポーネントは、アプリケーションの各部分の何らかの編成を必要とし、その後、フレームワークを扱っています。







プロジェクトのワイヤーフレームを取り除くことは、ライブラリを取り除くことよりもはるかに困難です。 ライブラリは、古いライブラリのAPI呼び出しを新しいライブラリの呼び出しで修正するか、ライブラリ実装を自分で記述することで置き換えることができます。 フレームワークは、特定の方法でアプリケーションを構築し、特定のルールに従ってコードの構造単位を編成、リンクすることを強制します。 さらに、ワイヤフレームは通常、ライブラリよりもはるかに複雑です。







これは、フレームワークの重要性を損なうものではなく、実績のある有名なアーキテクチャをプロジェクトにもたらし、アプリケーションを編成するためのルールを設定し、開発者が特定のソリューションを発明できないようにするフレームワークとして機能します。 これにより、ソフトウェア製品のサポートが強化されます。







理想的には、フレームワークの実装を簡単に変更できると便利です。 Javaの世界はこれに近づいていますが、仕様のおかげで、標準が設定され、そのAPI、およびさまざまなメーカーがそれを実装できます。







完全なソースコード








All Articles