javascript - কোথায় মডেল তথ্য এবং আচরণ করা?




model-view-controller angularjs dci (8)

আমি আমার সর্বশেষ প্রকল্পের জন্য AngularJS সঙ্গে কাজ করছি। ডকুমেন্টেশন এবং টিউটোরিয়াল সব মডেল তথ্য নিয়ামক সুযোগ মধ্যে করা হয়। আমি কনট্রোলারের জন্য এবং অনুরূপ মতামতের মধ্যে উপলব্ধ হতে হবে বুঝতে হবে।

তবে আমি আসলে মডেল বাস্তবায়িত করা উচিত মনে করি না। এটা জটিল হতে পারে এবং উদাহরণস্বরূপ ব্যক্তিগত বৈশিষ্ট্য আছে। উপরন্তু একটি অন্য প্রসঙ্গ / অ্যাপ্লিকেশন এটি পুনরায় ব্যবহার করতে পারেন। নিয়ামক মধ্যে সবকিছু নির্বাণ সম্পূর্ণরূপে এমভিসি প্যাটার্ন বিরতি।

একই মডেলের আচরণের জন্য সত্য রাখা। আমি ডেটা মডেল থেকে ডিসিআই আর্কিটেকচার এবং আলাদা আচরণ ব্যবহার করব, তাহলে আচরণের জন্য অতিরিক্ত বস্তু পরিচয় করিয়ে দিতে হবে। এই ভূমিকা এবং প্রসঙ্গ প্রবর্তন দ্বারা সম্পন্ন করা হবে।

অবশ্যই মডেল তথ্য এবং আচরণ সামঞ্জস্যপূর্ণ জাভাস্ক্রিপ্ট বস্তু বা কোনো "বর্গ" প্যাটার্ন সঙ্গে প্রয়োগ করা যেতে পারে। কিন্তু AngularJS উপায় কি এটা হবে? সেবা ব্যবহার করে?

তাই এটি এই প্রশ্নের নিচে আসে:

কিভাবে আপনি AngularJS সেরা অনুশীলন অনুসরণ, নিয়ামক থেকে decoupled মডেল বাস্তবায়ন করবেন?


Answers

Angularjs ডকুমেন্টেশন পরিষ্কারভাবে বলেছেন:

অনেক অন্যান্য ফ্রেমওয়ার্ক বিপরীত কৌণিক মডেল উপর কোন সীমাবদ্ধতা বা প্রয়োজনীয়তা করে তোলে। মডেল অ্যাক্সেস বা পরিবর্তন করার জন্য উত্তরাধিকারী বা বিশেষ অ্যাক্সেসর পদ্ধতিতে কোন ক্লাস নেই। মডেল আদিম, বস্তু হ্যাশ, বা একটি পূর্ণ বস্তু প্রকার হতে পারে। সংক্ষেপে মডেল একটি সাধারণ জাভাস্ক্রিপ্ট বস্তু।

সুতরাং এটি একটি মডেল ঘোষণা কিভাবে আপনি আপ। এটি একটি সহজ জাভাস্ক্রিপ্ট বস্তু।

আমি ব্যক্তিগতভাবে Angular পরিষেবাদি ব্যবহার করব না কারণ তারা ব্যবহার করতে পারে এমন সিঙ্গলটন বস্তুর মতো আচরণ করার উদ্দেশ্যে, উদাহরণস্বরূপ, আপনার আবেদন জুড়ে বিশ্বব্যাপী রাজ্যগুলি রাখতে।


আমি বর্তমানে এই প্যাটার্নটি চেষ্টা করছি, যা যদিও ডিসিআই নয়, একটি ক্লাসিক্যাল সার্ভিস / মডেল ডিকোপ্লিং প্রদান করে (ওয়েব পরিষেবাদি নিয়ে কথা বলার জন্য পরিষেবাগুলির সাথে (উর মডেল সিআরডুডি) এবং বস্তুর বৈশিষ্ট্য এবং পদ্ধতিগুলিকে সংজ্ঞায়িত করে মডেল)।

মনে রাখবেন যে যখনই মডেল অবজেক্টের নিজস্ব বৈশিষ্ট্যগুলিতে কাজ করার পদ্ধতিগুলির প্রয়োজন হয় তখনই আমি এই প্যাটার্নটি ব্যবহার করি, যা সম্ভবত আমি সর্বত্র ব্যবহার করব (যেমন উন্নত গেট্টার / সেট্টার)। আমি systematically প্রতি সেবা জন্য এই কাজ করার পক্ষে সমর্থন করছি না

সম্পাদনা করুন: আমি মনে করি এই প্যাটার্নটি "কৌণিক মডেলটি পুরানো জাভাস্ক্রিপ্ট অবজেক্ট" মন্ত্রের বিরুদ্ধে যাবে বলে মনে হয় তবে এখন মনে হচ্ছে এই প্যাটার্নটি পুরোপুরি সূক্ষ্ম।

EDIT (2): এমনকি আরও পরিষ্কার হতে, আমি কেবলমাত্র সাধারণ পেতে / সেটারগুলিকে ফ্যাক্টর করার জন্য মডেল ক্লাস ব্যবহার করি (উদাহরণস্বরূপ: টেমপ্লেটগুলিতে ব্যবহার করা)। বড় ব্যবসায়িক লজিকের জন্য, আমি আলাদা আলাদা পরিষেবা (গুলি) ব্যবহার করার সুপারিশ করি যা মডেল সম্পর্কে "জানেন", তবে তাদের থেকে আলাদা রাখা হয় এবং শুধুমাত্র ব্যবসায়িক যুক্তি অন্তর্ভুক্ত করে। যদি আপনি চান এটি একটি "ব্যবসায় বিশেষজ্ঞ" সেবা স্তর কল

সেবা / ElementServices.js (ঘোষণায় এলিমেন্ট কিভাবে ইনজেক্ট করা হয় তা লক্ষ্য করুন)

MyApp.service('ElementServices', function($http, $q, Element)
{
    this.getById = function(id)
    {
        return $http.get('/element/' + id).then(
            function(response)
            {
                //this is where the Element model is used
                return new Element(response.data);
            },
            function(response)
            {
                return $q.reject(response.data.error);
            }
        );
    };
    ... other CRUD methods
}

মডেল / Element.js (বস্তু সৃষ্টি জন্য তৈরি angularjs কারখানার ব্যবহার করে)

MyApp.factory('Element', function()
{
    var Element = function(data) {
        //set defaults properties and functions
        angular.extend(this, {
            id:null,
            collection1:[],
            collection2:[],
            status:'NEW',
            //... other properties

            //dummy isNew function that would work on two properties to harden code
            isNew:function(){
                return (this.status=='NEW' || this.id == null);
            }
        });
        angular.extend(this, data);
    };
    return Element;
});

আপনি একাধিক কন্ট্রোলার দ্বারা ব্যবহারযোগ্য কিছু করতে চান তাহলে আপনি পরিষেবা ব্যবহার করা উচিত। এখানে একটি সহজ রূপান্তরিত উদাহরণ:

myApp.factory('ListService', function() {
  var ListService = {};
  var list = [];
  ListService.getItem = function(index) { return list[index]; }
  ListService.addItem = function(item) { list.push(item); }
  ListService.removeItem = function(item) { list.splice(list.indexOf(item), 1) }
  ListService.size = function() { return list.length; }

  return ListService;
});

function Ctrl1($scope, ListService) {
  //Can add/remove/get items from shared list
}

function Ctrl2($scope, ListService) {
  //Can add/remove/get items from shared list
}

ডিসিআই একটি আদর্শ এবং এরকম কোনও angularJS উপায় নেই, ভাষাটি DCI সমর্থন করে না বা এটি না। আপনি যদি সোর্স ট্রান্সফর্মেশন ব্যবহার করতে ইচ্ছুক না হন এবং কিছু হ্রাস না করে থাকেন তবে JS ডিসিআইকে সমর্থন করে। আবার ডিসিআইর নির্ভরযোগ্যতা ইনজেকশনটির সাথে আর কোন সম্পর্ক নেই যে কোনও C # শ্রেণী আছে এবং অবশ্যই এটি কোনও পরিষেবা নয়। সুতরাং angulusJS এর ​​সাথে ডিসিআই করার সর্বোত্তম উপায় হল ডিসিআইকে JS পথটি করা, যা ডিসিআইকে প্রথম স্থানে কীভাবে প্রণয়ন করা যায় তার কাছাকাছি। সোর্স রূপান্তর না করা পর্যন্ত, আপনি সম্পূর্ণরূপে এটি করতে পারবেন না কারণ ভূমিকা পদ্ধতিগুলি প্রসঙ্গের বাইরেও বস্তুর অংশ হতে পারে তবে এটি সাধারণত ডিসিআই ভিত্তিক পদ্ধতি ইনজেকশন সমস্যা। আপনি যদি DCI এর জন্য authoritative সাইট fullOO.infoদেখেন তবে আপনি রুবি বাস্তবায়নের দিকে নজর রাখতে পারেন তারা পদ্ধতি ইনজেকশন ব্যবহার করে বা আপনি DCI- এ আরও তথ্যের জন্য here নজর রাখতে পারেন। এটি বেশিরভাগই রবি উদাহরণস্বরূপ, তবে ডিসিআই স্টাফগুলি এগুলি অগোছালো। ডিসিআই-র কীগুলির মধ্যে একটি হল যে সিস্টেমটি কী করে সিস্টেমটি থেকে পৃথক হয়। সুতরাং তথ্য অবজেক্ট বেশ মুঠোফোন কিন্তু একবার একটি প্রসঙ্গ ভূমিকা পদ্ধতিতে একটি ভূমিকা আবদ্ধ নির্দিষ্ট আচরণ উপলব্ধ করা। একটি ভূমিকা কেবল একটি সনাক্তকারী, আর কিছুই নয়, যে সনাক্তকারীর মাধ্যমে কোনও বস্তু অ্যাক্সেস করার সময় ভূমিকা পদ্ধতিগুলি উপলব্ধ। কোন ভূমিকা বস্তু / বর্গ আছে। পদ্ধতি ইনজেকশন সঙ্গে ভূমিকা পদ্ধতির scoping ঠিক যেমন বর্ণনা কিন্তু কাছাকাছি না। জেএস একটি প্রসঙ্গের একটি উদাহরণ হতে পারে

function transfer(source,destination){
   source.transfer = function(amount){
        source.withdraw(amount);
        source.log("withdrew " + amount);
        destination.receive(amount);
   };
   destination.receive = function(amount){
      destination.deposit(amount);
      destination.log("deposited " + amount);
   };
   this.transfer = function(amount){
    source.transfer(amount);
   };
}


অন্যান্য পোষ্টারদের দ্বারা বর্ণিত হিসাবে, অ্যাঙ্গুলার মডেলিংয়ের জন্য আউট অফ দ্য-বক্স বেস ক্লাস সরবরাহ করে না, তবে একজন দরকারীভাবে বেশ কয়েকটি ফাংশন সরবরাহ করতে পারে:

  1. একটি RESTful API সঙ্গে মিথস্ক্রিয়া এবং নতুন বস্তু তৈরি করার পদ্ধতি
  2. মডেলের মধ্যে সম্পর্ক স্থাপন করা
  3. ব্যাকএন্ডে থাকা আগে তথ্য যাচাই করা; বাস্তব সময় ত্রুটি প্রদর্শন করার জন্য দরকারী
  4. ক্যাশিং এবং অলস-লোডিং ক্ষতিকারক HTTP অনুরোধগুলি থেকে বিরত থাকার জন্য
  5. রাজ্য মেশিন হুক (সংরক্ষণ / আপডেট, আপডেট, তৈরি, নতুন, ইত্যাদি আগে)

এক লাইব্রেরি যা এই সমস্ত জিনিসগুলিকে ভাল করে তোলে ngActiveResource ( https://github.com/FacultyCreative/ngActiveResource )। সম্পূর্ণ প্রকাশ - আমি এই লাইব্রেরিটি লিখেছি - এবং আমি এটি বেশ কয়েকটি এন্টারপ্রাইজ-স্কেল অ্যাপ্লিকেশন নির্মাণে সফলভাবে ব্যবহার করেছি। এটি ভাল পরীক্ষিত, এবং একটি API সরবরাহ করে যা Rails ডেভেলপারদের কাছে পরিচিত হওয়া উচিত।

আমার দল এবং আমি সক্রিয়ভাবে এই লাইব্রেরিটি বিকাশ চালিয়ে যাচ্ছি, এবং আমি আরো কৌণিক বিকাশকারীদের এটি অবদান রাখতে এবং যুদ্ধ পরীক্ষাটি দেখতে চাই।


আমি এই ব্লগ পোস্টে যে সঠিক সমস্যা মোকাবেলা করার চেষ্টা করেছি।

মূলত, ডেটা মডেলিংয়ের জন্য সেরা হোম পরিষেবা এবং কারখানাগুলিতে রয়েছে। তবে, আপনার ডেটা এবং আপনার প্রয়োজনীয় আচরণগুলির জটিলতা সম্পর্কে আপনি কীভাবে পুনরুদ্ধার করেন তার উপর নির্ভর করে, বাস্তবায়নের বিষয়ে অনেকগুলি উপায় রয়েছে। কৌণিক বর্তমানে কোন মান উপায় বা সর্বোত্তম অনুশীলন আছে।

পোস্ট $ HTTP , $ সংস্থান , এবং Restangular ব্যবহার করে তিনটি পদ্ধতির জুড়ে।

এখানে কাজের মডেলের একটি কাস্টম getResult() পদ্ধতি সহ getResult() জন্য কিছু উদাহরণ কোড রয়েছে:

Restangular (সহজ peasy):

angular.module('job.models', [])
  .service('Job', ['Restangular', function(Restangular) {
    var Job = Restangular.service('jobs');

    Restangular.extendModel('jobs', function(model) {
      model.getResult = function() {
        if (this.status == 'complete') {
          if (this.passed === null) return "Finished";
          else if (this.passed === true) return "Pass";
          else if (this.passed === false) return "Fail";
        }
        else return "Running";
      };

      return model;
    });

    return Job;
  }]);

$ সম্পদ (সামান্য আরো convoluted):

angular.module('job.models', [])
    .factory('Job', ['$resource', function($resource) {
        var Job = $resource('/api/jobs/:jobId', { full: 'true', jobId: '@id' }, {
            query: {
                method: 'GET',
                isArray: false,
                transformResponse: function(data, header) {
                    var wrapped = angular.fromJson(data);
                    angular.forEach(wrapped.items, function(item, idx) {
                        wrapped.items[idx] = new Job(item);
                    });
                    return wrapped;
                }
            }
        });

        Job.prototype.getResult = function() {
            if (this.status == 'complete') {
                if (this.passed === null) return "Finished";
                else if (this.passed === true) return "Pass";
                else if (this.passed === false) return "Fail";
            }
            else return "Running";
        };

        return Job;
    }]);

$ http (হার্ডকোর):

angular.module('job.models', [])
    .service('JobManager', ['$q', '$http', 'Job', function($q, $http, Job) {
        return {
            getAll: function(limit) {
                var deferred = $q.defer();

                $http.get('/api/jobs?limit=' + limit + '&full=true').success(function(data) {
                    var jobs = [];
                    for (var i = 0; i < data.objects.length; i ++) {
                        jobs.push(new Job(data.objects[i]));
                    }
                    deferred.resolve(jobs);
                });

                return deferred.promise;
            }
        };
    }])
    .factory('Job', function() {
        function Job(data) {
            for (attr in data) {
                if (data.hasOwnProperty(attr))
                    this[attr] = data[attr];
            }
        }

        Job.prototype.getResult = function() {
            if (this.status == 'complete') {
                if (this.passed === null) return "Finished";
                else if (this.passed === true) return "Pass";
                else if (this.passed === false) return "Fail";
            }
            else return "Running";
        };

        return Job;
    });

ব্লগের পোস্ট নিজেই কেন আপনি প্রতিটি পদ্ধতির ব্যবহার করতে পারেন তার পাশাপাশি আপনার নিয়ামকগুলিতে মডেলগুলি কীভাবে ব্যবহার করবেন তা উদাহরণের উদাহরণের ভিত্তিতে আরও বিস্তারিতভাবে চলে যায়:

AngularJS ডেটা মডেল: $ HTTP ভিএস $ সম্পদ VS Restangular

একটি সম্ভাবনা আছে Angular 2.0 ডেটা মডেলিংয়ের আরো জোরালো সমাধান সরবরাহ করবে যা একই পৃষ্ঠায় প্রত্যেকেই পায়।


প্রচলিত (এবং ব্যাপকভাবে গৃহীত) উত্তরটি "নীচে", কারণ যেহেতু যেকোনো কিছু কার্যকর করার আগে সমস্ত DOM লোড করা হবে।

বিভিন্ন কারণে, বিভিন্ন পন্থাগুলির জন্য, ইচ্ছাকৃতভাবে একটি পৃষ্ঠা ওল্ড ইভেন্টের সাথে কার্যকর করার জন্য উপলভ্য অনুশীলনের সাথে শুরু হয়।





javascript model-view-controller angularjs dci