MVP паттерн

Хичээлээр анх IBM боловсруулан гаргасан Model View Presenter (MVP) - хэвийн талаар үзнэ. MVP нь MVC загвараас үүдэлтэй боловч програмын зохион байгуулалт талаасаа нилээд өөр хандлагатай. MVP паттерн MVC -г бодвол үзүүлбэр моделтой нягт холбоогүй байдаг онцлогтой. Доор зурагт MVP хэвийн бүтцийг харууллаа.

patt_04_01

Зургаас харахад контролерын оронд Presenter орж ирэн хэрэглэгчийн оруулсан өгөгдлийн шилжилт, загварын өөрчлөлтийг үзүүлбэрт тусгах үүргийг хариуцах болсон нь харагдана.

Presenter үзүүлбэртэй интерфейсээр дамжин харьцсанаар тестлэх боломжийг сайжруулна. Учир нь загварыг модулийн тестэд зориулагдсан тусгай загвараар сольж болно. MVP хэвийг MVC гийн адилаар програмын бизнес логик талаас авч үзцгээе.

patt_04_02

Бизнес логикийн талаас харвал MVP нь програмын бүхий л бизнес логикийг загварт багтаан харин өгөгдөлд хандалтын кодыг загвараас тусгаарласан нь MVC тэй адилхан. Энэ нь MVP нь MVC загвараас үүдэлтэйг батлана. MVP -д зөвхөн үзүүлбэрийн логик л өөр болсон.
Өмнөх хичээлүүдэд үзсэнтэй ижилхэн WPF програмын жишээг MVP паттернг ашиглан хийцгээе. Програмын бүтцийг дараах UML диаграмаар харууллаа.

patt_04_03

Үзүүлбэр IProjectsView интерфейсийг хэрэгжүүлэх ProjectsView классыг ашиглана. ProjectsView ба IProjectsView -д үзүүлбэрийг шинэчлэх, Presenter - тэй холбогдоход шаардлагатай бүхий л аргууд агуулагдана. Харин Presenter дотроо IProjectsView , IProjectsModel интерфейсийн төрлүүдийн холбоосыг ProjectsPresenter.view , ProjectsPresenter.model хэлбэрийн хувьсагч /шинж/ байдлаар агуулсан. Ийм зохион байгуулалт модел болон үзүүлбэрийн хоорондын харилцааг Presenter -ээр дамжуулан хийх боломжийг олгоно.
Бүтэц хэрхэн ажиллахыг тайлбарлая. Хэрвээ хэрэглэгч Update товчийг дарвал моделийг шинэчлэх ProjectsPresenter.view_ProjectUpdated() аргыг дуудах IProjectView.ProjectUpdated үйл явдлын боловсруулагч ажиллана. Загвар шинэчлэгдэх үед Presenter -ээр дамжин хэрэглэгчийн графикийн интерфейсийг шинэчлэх үйл явдлын IProjectsModel.ProjectUpdated боловсруулагч ажиллах юм. Эхэндээ загварын ажиллагааг ойлгоход хүндрэлтэй байж магадгүй. Түвшин хоорондын хамаарлыг бага болгохын тулд интерфейсийг хэрхэн ашиглаж байгааг сайн ойлгон аваарай. Ийм бүтцээр бичигдсэн програмыг цаашид хөгжүүлэх, кодыг ойлгоход цаг хугацаа, хүч хөдөлмөр хөнгөлдөг тул аргачлалыг өөрийн ажилдаа ашиглаж сурах хэрэгтэй. Бид үзүүлбэрийг үүсгэх логикийг Presenter -т шилжүүлсэн тул MVC загварыг бодвол тестлэх боломжоор хамаагүй илүү. MVC хэвд үзүүлбэрийг моделоос шууд үүсгэн өгдөг.
За одоо програмаа зохиоё. Програм MVC паттерн хичээлд үзсэнтэй яг адилхан ажиллана.

Модел

Visual StudioProjectBilling.UI.MVP нэртэй WPF шинэ төсөл үүсгээд Графикийн паттерн хичээлд үүсгэсэн ProjectBilling.DataAccess төслийн холбоосыг нэмэн өгөөрэй. Бид шинэ шийдэл /solution/ үүсгэсэн болохоор ProjectBilling.DataAccess төслийн холбоос үүсгэхийн тулд шийдэлд төслийг нэмэн оруулах хэрэгтэй. Үүний тулд шийдлийн нэр дээр баруун даралт хийхэд гарч ирэх цэснээс Add->Existing Project гэж ороод ProjectBilling.DataAccess төслийг заан өгнө. Төсөл шийдэлд нэмэгдсэний дараа ProjectBilling.UI.MVP төслийн Reference дээр баруун даралт хийгээд Add Reference цэсээр ороод доорх зурагт үзүүлснээр ProjectBilling.DataAccess төслийн холбоосыг нэмнэ.

patt_04_04

ProjectBilling.UI.MVP төсөлд дараах агуулга бүхий ProjectsModel классыг нэмнэ.

using System;
using System.Collections.Generic;
using System.Linq;
using ProjectBilling.DataAccess;

namespace ProjectBilling.Business
{
    #region ProjectsEventArgs

    public class ProjectEventArgs : EventArgs
    {
        public Project Project { get; set; }
        public ProjectEventArgs(Project project)
        {
            Project = project;
        }
    }

    #endregion ProjectsEventArgs

    public interface IProjectsModel
    {
        void UpdateProject(Project project);
        IEnumerable<Project> GetProjects();
        Project GetProject(int Id);
        event EventHandler<ProjectEventArgs> ProjectUpdated;
    }

    public class ProjectsModel : IProjectsModel
    {
        private IEnumerable<Project> projects = null;

        public event EventHandler<ProjectEventArgs>
            ProjectUpdated = delegate { };

        public ProjectsModel()
        {
            projects = new DataServiceStub().GetProjects();
        }

        public void UpdateProject(Project project)
        {
            ProjectUpdated(this,
                new ProjectEventArgs(project));
        }

        public IEnumerable<Project> GetProjects()
        {
            return projects;
        }


        public Project GetProject(int Id)
        {
            return projects.Where(p => p.ID == Id)
                .First() as Project;
        }
    }
}

Моделийн класс ProjectsModel доорх гишүүдтэй IProjectsModel интерфейсийг хэрэгжүүлж байгаа.

  • UpdateProject() арга төслийг шинэчлэнэ. Аргыг төлвөөр дамжуулан шинэчлэлийг хийж болохоор өргөжүүлж болох ч энд энгийн байлгах үүднээс үүнийг авч үзээгүй.
  • GetProjects() төслүүдийн жагсаалтыг авчирна.
  • GetProject() төслийг ID -гаар нь буцаана
  • ProjectUpdated төсөлд өөрчлөлт ороход дуудагдах үйл явдал.

ProjectEventArgs бол гишүүдийг нь үйл явдлын ProjectUpdated боловсруулагч ашиглаж болох туслах класс

Үзүүлбэр

Үзүүлбэрийг ProjectView.xaml , ProjectView.xaml.cs файлууд үүсгэнэ. Төсөлд үзүүлбэрийг нэмэхийн тулд төслийн нэр дээр баруун даралт хийхэд гарч ирэх цэснээс Add->Window гэж ороод үзүүлбэрийн нэрээ өгөхөд VS засварлагч .xaml, .cs өргөтгөлтэй файлуудыг төсөлд нэмэн оруулна. ProjectView.xaml файл дараах агуулгатай байна.

<Window x:Class="ProjectBilling.UI.MVP.ProjectsView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="Төслүүд" MinHeight="265" Height="265"
        MinWidth="250" Width="250">
    <StackPanel>
        <Label Content="Төсөл:" Margin="5, 0, 5, 0" />
        <ComboBox Name="projectsComboBox" Margin="5, 0, 5, 0"
                SelectionChanged="projectsComboBox_SelectionChanged" />
        <Label Content="Нэр:" Margin="5, 0, 5, 0" />
        <TextBox Name="nameTextBox" Margin="5, 0, 5, 0"
                IsEnabled="False" />
        <Label Content="Тооцооны өртөг:" Margin="5, 0, 5, 0" />
        <TextBox Name="estimatedTextBox" Margin="5, 0, 5, 0"
                IsEnabled="False" />
        <Label Content="Гүйцэтгэлийн өртөг:" Margin="5, 0, 5, 0" />
        <TextBox Name="actualTextBox" Margin="5, 0, 5, 0"
                IsEnabled="False" />
        <Button Name="updateButton" Content="Update"
                Margin="5, 10, 5, 0" IsEnabled="False"
                Click="updateButton_Click" />
    </StackPanel>
</Window>

Формын кодыг үзүүлбэл

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using ProjectBilling.Business;
using ProjectBilling.DataAccess;

namespace ProjectBilling.UI.MVP
{

    public interface IProjectsView
    #region IProjectsView
    {
        int NONE_SELECTED { get; }
        int SelectedProjectId { get; }
        void UpdateProject(Project project);
        void LoadProjects(IEnumerable<Project> projects);
        void UpdateDetails(Project project);
        void EnableControls(bool isEnabled);
        void SetEstimatedColor(Color? color);
        event EventHandler<ProjectEventArgs> ProjectUpdated;
        event EventHandler<ProjectEventArgs> DetailsUpdated;
        event EventHandler SelectionChanged;
    }

    #endregion IProjectsView

    #region ProjectsView


    public partial class ProjectsView : Window, IProjectsView
    {
        #region Initialization

        public int NONE_SELECTED { get { return -1; } }
        public event EventHandler<ProjectEventArgs>
        ProjectUpdated = delegate { };
        public int SelectedProjectId { get; private set; }

        public event EventHandler SelectionChanged
            = delegate { };
        public event EventHandler<ProjectEventArgs>
            DetailsUpdated = delegate { };

        public ProjectsView()
        {
            InitializeComponent();
            SelectedProjectId = NONE_SELECTED;
        }

        #endregion Initialization

        #region Event handlers

        private void updateButton_Click(object sender,
            RoutedEventArgs e)
        {
            Project project = new Project();
            project.Name = nameTextBox.Text;
            project.Estimate =
                GetDouble(estimatedTextBox.Text);
            project.Actual =
                GetDouble(actualTextBox.Text);
            project.ID =
                int.Parse(
                    projectsComboBox.SelectedValue.
                        ToString());
            ProjectUpdated(this,
                new ProjectEventArgs(project));
        }

        private void projectsComboBox_SelectionChanged(
            object sender, SelectionChangedEventArgs e)
        {
            SelectedProjectId
                = (projectsComboBox.SelectedValue == null)
                      ? NONE_SELECTED
                      : int.Parse(
                          projectsComboBox.SelectedValue.
                              ToString());
            SelectionChanged(this,
                new EventArgs());
        }

        #endregion Event handlers

        #region Public methods

        public void UpdateProject(Project project)
        {
            IEnumerable<Project> projects =
                projectsComboBox.ItemsSource as
                    IEnumerable<Project>;
            Project projectToUpdate =
                projects.Where(p => p.ID == project.ID)
                    .First() as Project;
            projectToUpdate.Name = project.Name;
            projectToUpdate.Estimate = project.Estimate;
            projectToUpdate.Actual = project.Actual;
            if (project.ID == SelectedProjectId)
                UpdateDetails(project);
        }

        public void LoadProjects(IEnumerable<Project> projects)
        {
            projectsComboBox.ItemsSource = projects;
            projectsComboBox.DisplayMemberPath = "Name";
            projectsComboBox.SelectedValuePath = "ID";
        }

        public void EnableControls(bool isEnabled)
        {
            estimatedTextBox.IsEnabled = isEnabled;
            actualTextBox.IsEnabled = isEnabled;
            updateButton.IsEnabled = isEnabled;
        }

        public void SetEstimatedColor(Color? color)
        {
            estimatedTextBox.Foreground
                = (color == null)
                      ? actualTextBox.Foreground
                      : new SolidColorBrush((Color)color);
        }

        public void UpdateDetails(Project project)
        {
            nameTextBox.Text = project.Name;
            estimatedTextBox.Text
                = project.Estimate.ToString();
            actualTextBox.Text
                = project.Actual.ToString();
            DetailsUpdated(this,
                new ProjectEventArgs(project));
        }

        #endregion Public methods

        #region Helpers

        private double GetDouble(string text)
        {
            return string.IsNullOrEmpty(text)
                ? 0 : double.Parse(text);
        }

        #endregion Helpers

    }

    #endregion ProjectsView
}

байна. Кодын бүтэц дээр үзүүлсэн UML диаграмтай тохирно.

Presenter

Presenter -ыг ердийн класс нэмэх байдлаар оруулна. Харин классын нэрийг ProjectsPresenter гэж өгөөд доорх агуулгыг оруулан өгөөрэй.

using System;
using System.Windows.Media;
using ProjectBilling.Business;
using ProjectBilling.DataAccess;

namespace ProjectBilling.UI.MVP
{
    public class ProjectsPresenter
    {
        #region Initialization

        private IProjectsView view = null;
        private IProjectsModel model = null;

        public ProjectsPresenter(IProjectsView projectsView,
            IProjectsModel projectsModel)
        {
            view = projectsView;
            view.ProjectUpdated += view_ProjectUpdated;
            view.SelectionChanged
                += view_SelectionChanged;
            view.DetailsUpdated += view_DetailsUpdated;
            model = projectsModel;
            model.ProjectUpdated += model_ProjectUpdated;
            view.LoadProjects(
                model.GetProjects());
        }

        #endregion Initialization

        #region Event handlers

        private void view_DetailsUpdated(object sender,
            ProjectEventArgs e)
        {
            SetEstimatedColor(e.Project);
        }

        private void view_SelectionChanged(object sender,
            EventArgs e)
        {
            int selectedId = view.SelectedProjectId;
            if (selectedId > view.NONE_SELECTED)
            {
                Project project =
                    model.GetProject(selectedId);
                view.EnableControls(true);
                view.UpdateDetails(project);
                SetEstimatedColor(project);
            }
            else
            {
                view.EnableControls(false);
            }
        }

        private void model_ProjectUpdated(object sender,
            ProjectEventArgs e)
        {
            view.UpdateProject(e.Project);
        }

        private void view_ProjectUpdated(object sender,
            ProjectEventArgs e)
        {
            model.UpdateProject(e.Project);
            SetEstimatedColor(e.Project);
        }

        #endregion Event handlers

        #region Helpers

        private void SetEstimatedColor(Project project)
        {
            if (project.ID == view.SelectedProjectId)
            {
                if (project.Actual <= 0)
                {
                    view.SetEstimatedColor(null);
                }
                else if (project.Actual
                         > project.Estimate)
                {
                    view.SetEstimatedColor(Colors.Red);
                }
                else
                {
                    view.SetEstimatedColor(Colors.Green);
                }
            }
        }

        #endregion Helpers
    }
}

Энд үйл явдлын дараах боловсруулагчдыг тодорхойлсон.

  • view_DetailsUpdated боловсруулагч IProjectsView.DetailsUpdated үйл явдлын хариу байдлаар дуудагдах бөгөөд төслийн гүйцэтгэлийн өртөгийг харуулах TextBox -ийн өнгийг шинэчлэх SetEstimateColor() аргыг дуудна.
  • view_SelectionChanged нь IProjectsView.SelectionChanged үйл явдал үүсэхэд үзүүлбэрийг өөрчилнө. Үйл явдал ComboBox -д шинэ төслийг сонгоход үүснэ.
  • model_ProjectUpdated боловсруулагч IProjectsModel.ProjectUpdate -ийн хариуд дуудагдан модел ба үзүүлбэрийн шинэчлэлтийг ажиллуулна.

Хэрвээ та хэвүүд ашиглан програм зохиож байгаагүй бол код ойлгомжгүй байж мэднэ. C# хэлний мэдлэгтэй бол энд бичсэн кодууд их энгийн учраас юу хийж байгааг ойлгоход амархан. Хамгийн гол зүйл бол паттерныг ашиглан програмын кодыг хэрхэн зохион байгуулж байгааг сурах юм. Хэвийг ОХП-ын ямарч хэлэнд ашиглаж болно.
Одоо програмын эхлэлийн цонх MainWindow.xaml -аас ProjectsView үзүүлбэрийг нээх боломжтой болгохын тулд MainWindow.xaml -д доорх өөрчлөлтийг оруулъя.

<Window x:Class="ProjectBilling.UI.MVP.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="250" Width="250"
        MinHeight="250" MinWidth="250">
    <StackPanel>
        <Button Content="Төслийг үзүүлэх"
                Name="showProjectsButton" Margin="5, 10, 5, 0"
                Click="showProjectsButton_Click" />
    </StackPanel>
</Window>

Үндсэн цонхонд төслийн үзүүлбэрийг харуулах товч нэмсэн тул MainWindow.cs файлын агуулгыг доорх байдлаар өөрчлөөрэй.

using System.Windows;
using ProjectBilling.Business;

namespace ProjectBilling.UI.MVP
{
    public partial class MainWindow : Window
    {
        private IProjectsModel model = null;

        public MainWindow()
        {
            InitializeComponent();
            model = new ProjectsModel();
        }

        private void showProjectsButton_Click(object sender,
            RoutedEventArgs e)
        {
            ProjectsView view = new ProjectsView();
            ProjectsPresenter presenter
                = new ProjectsPresenter(view, model);
            view.Owner = this;
            view.Show();
        }
    }
}

Програмыг ажлуулбал MVC паттерн хичээлд хийсэн жишээтэй ижилхэн үр дүн гарч ирнэ. Энд MVP -д ашиглаж байгаа Presenter бүтэц л чухал. Танд ийм амархан зүйлийг хэтэрхий их ажил нэмэн хийгээд байгаа мэт санагдаж магадгүй. Сургалтын жишээнд л ингэж санагдана. Програм том хэмжээний олон асуудлыг шийдэх хэрэгтэй болоход хэвийн ач тус мэдрэгдэнэ. Хэвийн ерөнхий бүтцийг гаргах ажиллагаа нь таны програмын том жижгээс хамаарахгүй учраас л тэгж санагдаж байгаа юм. Цааш програмын хэмжээ томрох үед энэ загвараа ашиглаад явах болохоор асуудал багатай. MVC -тэй харьцуулбал MVP нилээд дэвшлийг авчирсан.

  • MVP нь Presenter -ээр дамжуулан төлвийн шалгалт, үзүүлбэрийн логикийг удирдах боломжийг өгсөн.
  • Үзүүлбэрийг моделоос бүрэн салгаж тэдгээрийн холбоог Presenter -ээр дамжуулан зохион байгуулсан.

MVP нь MVC гээс ялгаатай нь IView интерфейсийг ашигласнаар загварт шууд өөрчлөлт хийхгүйгээр бизнес логикийг дахин ашиглах боломжийг олгодог. Жишээ нь та энэ WPF програмыг Silverlight рүү шилжүүлэх хэрэгтэй болбол Silverlight дээр IProjectsView интерфейсийг хэрэгжүүлсэн үзүүлбэрийг л зохиох хэрэгтэй. Харин IProjectsPresenter, IProjectsModel интерфейсүүдийг өөрчлөлтгүйгээр дахин ашиглаж болно.        

Хичээлийг сайн судлаад ерөнхий санааг сайн ойлгож аваарай.

Мэдээлэл таалагдсан бол найзуудтайгаа хуваалцаарай.

  Нээгдсэн тоо: 58 Төлбөртэй

Үйл явдал /event/ тодорхой үйлдэл хийгдсэн талаар системд мэдэгддэг. Хэрвээ бид энэхүү үйлдлийг ажиглах хэрэгтэй бол яг энд үйл явцыг хэрэглэж болно.
Жишээ болгоод банкны дансыг тодорхойлох 

class Account
{
    // дансны үлдэгдэл
    public int Sum { get; private set; }
    // байгуулагчаар дансны эхний үлдэгдлийг тогтооно
    public Account(int sum) => Sum = sum;
    // дансанд мөнгө хийх
    public void Put(int sum) => Sum += sum;
    // данснаас мөнгө авах
    public void Take(int sum)
    {
        if (Sum >= sum)
        {
            Sum -= sum;
        }
    }
}

классийг аваад үзье. Байгуулагчид Sum шинжид хадгалагдах эхний үлдэгдлийг тогтооно. Put аргаар дансанд мөнгө хийнэ.

  Нээгдсэн тоо: 354 Бүртгүүлэх

Хувьсагч, нөхцөлт бүтэц, цикл, массив ойлголтуудтай танилцсан тул жижиг хэмжээний програмийг зохиох боломжтой болсон. Иймээс массивуудтай ажиллах хэдэн бодлогыг авч үзье.

Санамж. Програмчлалын хэлийг сурахад дадлага чухал үүрэгтэй. Жижиг гэлтгүй асуудлуудыг өөрөө шийдэхээс л дадлагажин код бичиж сурдаг. Эхлэн суралцагсад асуудлыг бэлэн сангууд ашиглан шийдэх гэдэг нь цаашид асуудал үүсгэх үндэс болдог. Хичээлийн жишээнүүдийг бэлэн сан ашиглан маш хурдан шийдэж болох ч чухам ямар ажиллагаануудыг хийсэнг мэдэлгүй өнгөрнө. Өөрөөр хэлбэл кодийн алгоритмийг ойлголгүй ажиллагааг шийднэ гэсэн үг. Ийм аргаар бүх асуудлыг шийдэх боломжгүй гэдэг нь тодорхой. Ер код бичих суурь бол асуудлыг шийдэх алгоритмыг зохиож сурах. Үүнд суралцахгүйгээр код бичиж сурахгүй гэдгийг сануулъя.

  Нээгдсэн тоо: 350 Төлбөртэй

Делегат нь аргыг заасан обьектоор илэрхийлэгдэнэ. Өөрөөр хэлбэл делегат гэдэг нь аргын заагч бөгөөд түүгээр тухайн аргыг дуудаж болно.

Делегатийн тодорхойлолт

Делегатийг зарлахдаа delegate түлхүүр үгийг ашиглах ба түүний араас буцаах төрөл, нэр, параметрүүд байрлана. Жишээ нь

delegate void Message();

Message делегатийн буцаах төрөл void (өөрөөр хэлбэл юу ч буцаахгүй) бөгөөд ямарч параметрийг авахгүй. Энэ нь Message делегат ямарч параметр авдаггүй бөгөөд юу ч буцаадаггүй дурын аргыг зааж болно гэсэн үг.
Message делегатийн хэрэглэгээг

Message mes;            // 2. делегатийн хувьсагчийг үүсгэх
mes = Hello;            // 3. хувьсагчид аргын хаягийг олгох
mes();                  // 4. аргыг дуудах

void Hello() => Console.WriteLine("Hello World");
delegate void Message(); // 1. делегатийг зарлах

үзүүлсэн дээрх кодийг авч үзье.

  Нээгдсэн тоо: 278 Төлбөртэй

.NET фреймворк ердийн төрлүүдээс гадна ерөнхийлөгдсөн (generics) төрлүүд болон ерөнхийлөгдсөн аргуудын үүсгэлтийг дэмждэг. Энэхүү боломжийн онцлогийг судлахын өмнө ерөнхийлөгдсөн төрлүүд байхгүй бол үүсч болох асуудлуудыг авч үзье. Жишээ нь

class Person
{
    public int Id { get;}
    public string Name { get;}
    public Person(int id, string name)
    {
        Id = id;
        Name = name;
    }
}

гэж хэрэглэгчийн өгөгдлийг хадгалах классийг тодорхойллоо гэж үзье. Person класст Id - хэрэглэгчийн давтагдахгүй идентификатор, Name - хэрэглэгчийн нэр гэсэн хоёр шинжийг тодорхойлсон. Энд хэрэглэгчийн идентификаторийг тоон утгаар өгсөн тул шинж 1, 2, 3, 4 гэх мэтээр утгуудыг авна.

Үйл явдал /event/ тодорхой үйлдэл хийгдсэн талаар системд мэдэгддэг. Хэрвээ бид энэхүү үйлдлийг ажиглах хэрэгтэй бол яг энд…

Нээгдсэн тоо : 58

 

Манай төсөл олон хуудсуудтай болон тэдгээрийн хооронд динамикаар шилжилт хийж байгаа ч тухайн үед шилжилт хийгдсэн хуудаст тохирох…

Нээгдсэн тоо : 90

 

Зочин (Visitor) паттерн классуудыг өөрчлөхгүйгээр тэдгээрийн обьектуудын үйлдлийг тодорхойлох боломжийг олгоно. Зочин хэвийг ашиглахдаа классуудын хоёр ангилалыг тодорхойлно.…

Нээгдсэн тоо : 86

 

Лямбда-илэрхийлэл нь нэргүй аргын хураангуй бичилтийг илэрхийлнэ. Лямбда-илэрхийлэл утга буцаадаг, буцаасан утгыг өөр аргын…

Нээгдсэн тоо : 204

 

Кодийн сайжруулалт /рефакторинг/ хичээлээр програмийн кодоо react -ийн зарчимд нийцүүлэн компонентод салгасан.…

Нээгдсэн тоо : 245

 

Хадгалагч (Memento) хэв обьектын дотоод төлвийг түүний гадна гаргаж дараа нь хайрцаглалтын зарчмыг зөрчихгүйгээр обьектыг сэргээх боломжийг олгодог.

Нээгдсэн тоо : 254

 

Делегаттай нэргүй арга нягт холбоотой. Нэргүй аргуудыг делегатийн хувийг үүсгэхэд ашигладаг.
Нэргүй аргуудын тодорхойлолт delegate түлхүүр үгээр…

Нээгдсэн тоо : 297

 

Математикт харилцан урвуу тоонууд гэж бий. Ямар нэгэн тооны урвуу тоог олохдоо тухайн тоог сөрөг нэг зэрэг дэвшүүлээд…

Нээгдсэн тоо : 285

 

Төсөлд react-router-dom санг оруулан чиглүүлэгчдийг бүртгүүлэн тохируулсан Санг суулган тохируулах хичээлээр бид хуудас…

Нээгдсэн тоо : 369

 
Энэ долоо хоногт

функцийн интервал дахь хамгийн бага утгыг ол.

Нээгдсэн тоо : 855

 

Зөв дөрвөн өнцөгт пирамидын өндөр 4. Хажуу ирмэг суурийн хавтгайд 30 градусын өнцгөөр налсан бол пирамидын хажуу ирмэгийг ол.

Нээгдсэн тоо : 1848

 

бол M·N=?

Нээгдсэн тоо : 1161