Training Azure DevOps

Pada tanggal 20-22 September 2021, saya mendapat kesempatan untuk mendeliver online training dengan topik Azure DevOps, pelatihan ini diikuti oleh developer, dan kepala bagian IT Dept dari Universitas Unika AtmaJaya Jakarta.

Pada pelatihan ini dibahas beberapa topik seperti:

  • Apa itu DevOps
  • Pengenalan Azure DevOps
  • Memilih pendekatan agile yg akan digunakan
  • Bekerja dengan Azure Boards
  • Apa itu Delivery Plan
  • Pengaturan environment yg akan digunakan
  • Merencanakan sprint menggunakan Delivery Plans
  • Apa itu Azure Pipeline
  • Membuat Pipeline
  • Multiple konfigurasi pipeline
  • Memilih code workflow strategy
  • Bagaimana membuat pull request pada github
  • Push change dan mentrigger pipeline
  • Pelacakan build history
  • Penambahan rule review pada saat pull request
  • Apa itu Automated Testing?
  • Menambahkan unit testing pada aplikasi
  • Menjalankan unit testing pada pipeline
  • Menambahkan testing widget pada dashboard
  • Menjalankan code coverage testing
  • Memperbaiki failed test
  • Apa itu Azure Artifacts
  • Membuat package pada Azure Artifacts
  • Membuat Release pipeline stage
  • Apa itu continuous delivery
  • Deploy app to Azure App Services
  • Monitor health pipeline
  • Membuat multistages pipeline (dev, staging)

imageimage

Advertisement

[Xamarin Forms Series] – Menggunakan Library MVVM Helper – Part 2

Tutorial berikut adalah lanjutan dari tutorial MVVM dengan Xamarin Forms 5 yang sudah ditulis sebelumnya.

Untuk mempermudah penggunaan MVVM di Xamarin, anda dapat menggunakan library MVVMHelper. Library ini mendukung beberapa fitur yang sangat membantu kita dalam mengimplementasikan pola MVVM. Fitur-fitur tersebut diantarannya ViewModelBase, AsyncCommand dan ObservableRangeCollection.

Untuk menambahkan library MVVMHelper pada solution, tambahkan package manager berikut ini. Klik kanan pada solution, kemudian cari library MVVMHelpers

Setelah itu buat class dengan nama ViewModelBase yang diturunkan dari class BaseViewModel yang ada pada MVVMHelper.

    public class ViewModelBase : BaseViewModel
    {
    }

Kemudian buat class dengan nama CoffeeEquipmentViewModel.cs pada folder ViewModel. Disini kita akan menambahkan o ObservableRange yang akan digunakan sebagai sumber data pada ListView.

namespace MyXamarinApps.ViewModels
{
    public class CoffeeEquipmentViewModel : ViewModelBase
    {
        public ObservableRangeCollection<string> Coffee { get; set; }

        public ICommand IncreaseCount { get; }

        public ICommand CallServerCommand { get;}

        public CoffeeEquipmentViewModel()
        {
            IncreaseCount = new Command(OnIncrease);
            CallServerCommand = new AsyncCommand(CallServer);
            Coffee = new ObservableRangeCollection<string>();
            Title = "Coffee Equipment";
        }

        async Task CallServer()
        {
            var items = new List<string> { "Luwak Coffee", "Aceh Gayo", "Toraja Coffee" };
            Coffee.AddRange(items);
        }

        int count = 0;
        private string countDisplay = "Click Me";
        public string CountDisplay
        {
            get => countDisplay;
            set => SetProperty(ref countDisplay, value);
        }

        private void OnIncrease()
        {
            count++;
            CountDisplay = $"You clicked {count} time";
        }
    }
}

Tambahkan class Coffee di folder Model.

    public class Coffee
    {
        public string Roaster { get; set; }
        public string Name { get; set; }
        public string Image { get; set; }
    }

Kemudian modifikasi class CoffeeEquipmentViewModel

namespace MyXamarinApps.ViewModels
{
    public class CoffeeEquipmentViewModel:ViewModelBase
    {
        public ObservableRangeCollection<Coffee> Coffee { get; set; }
        public ObservableRangeCollection<Grouping<string,Coffee>> CoffeeGroup { get; set; }
        public AsyncCommand RefreshCommand { get; }
        public AsyncCommand<Coffee> FavoriteCommand { get; set; }
        public AsyncCommand<object> SelectedCommand { get; set; }

        public CoffeeEquipmentViewModel()
        {
            Title = "Coffee Equipment";
            Coffee = new ObservableRangeCollection<Coffee>();
            CoffeeGroup = new ObservableRangeCollection<Grouping<string, Coffee>>();
            var image = "luwak.png";

            Coffee.Add(new Coffee { Roaster = "Otten Coffee", Name = "Italian Roasted", Image = image });
            Coffee.Add(new Coffee { Roaster = "Blue Bottle", Name = "Aceh Gayo", Image = image });
            Coffee.Add(new Coffee { Roaster = "Blue Bottle", Name = "Darked Roasted", Image = image });
            Coffee.Add(new Coffee { Roaster = "Otten Coffee", Name = "Kenya Kiambu", Image = image });
            Coffee.Add(new Coffee { Roaster = "Yes Plz", Name = "Pike Market", Image = image });
            Coffee.Add(new Coffee { Roaster = "Otten Coffee", Name = "Toraja", Image = image });

            CoffeeGroup.Add(new Grouping<string, Coffee>("Otten Coffee",Coffee.Where(c=>c.Roaster== "Otten Coffee")));
            CoffeeGroup.Add(new Grouping<string, Coffee>("Blue Bottle", Coffee.Where(c => c.Roaster == "Blue Bottle")));
            
            RefreshCommand = new AsyncCommand(Refresh);
            FavoriteCommand = new AsyncCommand<Coffee>(Favorite);
            SelectedCommand = new AsyncCommand<object>(SelectedCoffee);
        }

        private async Task SelectedCoffee(object arg)
        {
            var coffee = arg as Coffee;
            if (coffee == null) return;
            await Application.Current.MainPage.DisplayAlert("Selected", coffee.Name, "OK");
        }

        private async Task Favorite(Coffee coffee)
        {
            if (coffee == null)
                return;
            await Application.Current.MainPage.DisplayAlert("Favorite", $"{coffee.Roaster} - {coffee.Name}", "OK");
        }

        private async Task Refresh()
        {
            IsBusy = true;
            await Task.Delay(2000);
            IsBusy = false;
        }
    }
}

Pada XAML tambahkan kode berikut untuk membinding objek ViewModel yang sudah kita buat sebelumnya.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:viewmodels="clr-namespace:SampleMVVM.ViewModels"
             x:Class="MyXamarinApps.ViewModels">

    <ContentPage.BindingContext>
        <viewmodels:CoffeeEquipmentViewModel />
    </ContentPage.BindingContext>

    <ListView BackgroundColor="Transparent" 
              ItemsSource="{Binding Coffee}"
              HasUnevenRows="True"
              SeparatorVisibility="None">
        <ListView.ItemTemplate>
            <DataTemplate>
                <ViewCell>
                    <ViewCell.ContextActions>
                        <MenuItem Text="Favorite" />
                        <MenuItem IsDestructive="True" Text="Delete" />
                    </ViewCell.ContextActions>
                    <Grid Padding="10">
                        <Frame CornerRadius="20" HasShadow="True">
                            <StackLayout Orientation="Horizontal">
                                <Image Source="{Binding Image}" WidthRequest="66" />
                                <StackLayout VerticalOptions="Center">
                                    <Label
                                        FontSize="Large"
                                        Text="{Binding Name}"
                                        VerticalOptions="Center" />
                                    <Label
                                        FontSize="Large"
                                        Text="{Binding Roaster}"
                                        VerticalOptions="Center" />
                                </StackLayout>
                            </StackLayout>
                        </Frame>
                    </Grid>
                </ViewCell>
            </DataTemplate>
        </ListView.ItemTemplate>
        <ListView.Header>
            <StackLayout Orientation="Horizontal">
                <Label HorizontalOptions="Center" Text="Coffee of the World" />
            </StackLayout>
        </ListView.Header>
        <ListView.Footer>
            <StackLayout HorizontalOptions="Center" Orientation="Horizontal">
                <Button Text="Load More" />
            </StackLayout>
        </ListView.Footer>
    </ListView>
</ContentPage>

Jalankan aplikasinya untuk melihat tampilan List yang mengambil data contoh dari ViewModel yang sudah dibuat sebelumnya. Dari contoh ini dapat dilihat bahwa dengan menggunakan MVVMHelper kita dapat menggunakan objek ObservableRange yang fleksible untuk digunakan sebagai tempat menampung objek bertipe List. Selain itu MVVMHelper juga mendukung AsyncCommand untuk membuat command yang mendukung async method.

[Xamarin Forms Series] – Menggunakan MVVM Pattern di Xamarin Forms 5 – Part 1

Apa itu MVVM pada Xamarin Forms?

Pengembang Xamarin.Forms biasanya membuat antarmuka pengguna di XAML, dan kemudian menambahkan kode di belakang( code behind). Saat aplikasi dimodifikasi, kode bertambah banyak, dan kompleksitas bertambah, masalah pemeliharaan akan muncul. Masalah-masalah ini termasuk ketergantungan ketat (tight coupling) antara kontrol UI dan logika bisnis, yang akan meningkatkan biaya pembuatan modifikasi UI, dan kesulitan ketika  menggunakan unit testing terhadap kode tersebut.

Model-View-ViewModel (MVVM) membantu memisahkan logika bisnis dan presentasi aplikasi dari antarmuka pengguna (UI). Mempertahankan pemisahan yang bersih (loose coupling) antara logika aplikasi dan UI akan membantu mengatasi berbagai masalah pengembangan dan dapat membuat aplikasi lebih mudah untuk diuji, dipelihara, dan dikembangkan. Ini juga dapat meningkatkan peluang penggunaan kembali kode dan memungkinkan pengembang dan desainer UI untuk lebih mudah berkolaborasi saat mengembangkan bagian aplikasi masing-masing.

Ada tiga komponen inti dalam MVVM yaitu model, view, dan view mode. Masing-masing mempunyai  tanggung jawab  yang berbeda. Gambar berikut  menunjukkan hubungan antara tiga komponen.

View bertanggung jawab untuk menentukan struktur, tata letak, dan tampilan dari apa yang dilihat pengguna di layar. Idealnya, setiap tampilan didefinisikan dalam XAML, dengan code behind seminimal mungkin yang tidak mengandung logika bisnis. Namun, dalam beberapa kasus, code behind mungkin berisi logika UI yang mengimplementasikan perilaku visual yang sulit diekspresikan dalam XAML, seperti animasi.

View Model mengimplementasikan properti dan command yang akan dibinding kedalam tampilan, dan memberi tahu tampilan tentang perubahan status apa pun melalui peristiwa pemberitahuan perubahan (notify property changed). Properti dan command yang disediakan view model menentukan fungsionalitas yang akan ditawarkan oleh UI, tetapi view menentukan bagaimana fungsionalitas itu akan ditampilkan.

Kelas Model adalah kelas non-visual yang merangkum data yg digunakan pada aplikasi. Oleh karena itu, model dapat dianggap mewakili model domain aplikasi, yang biasanya menyertakan model data bersama dengan logika bisnis dan validasi. Contoh objek model termasuk data transfer object (DTO), Plain Old C# Object (POCO), dan objek entitas.

Pada contoh dibawah ini akan ditunjukan cara menggunakan mvvm pattern di Xamarin Forms.

Buat Content Page dengan nama CoffeeEquipmentPage.xaml pada folder View

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
             x:Class="SampleMVVM.Views.CoffeeEquipmentPage">
    <Grid RowDefinitions="*,Auto,Auto,*">
    <Label Grid.Row="1" HorizontalOptions="Center"
               FontSize="Large" Text="{Binding CountDisplay}" />
<Button x:Name="btnCount" Clicked="btnCount_Clicked" Grid.Row="2" Text="Click Me" />
    </Grid>
</ContentPage>

Kemudian tambahkan code behind sebagai berikut. Properti CountDisplay akan dibinding kedalam Label. Pada contoh dibawah ini masih digunakan event handler untuk aktivitas penekanan tombol, namun pada contoh selanjutnya akan digunakan object Command.

namespace SampleMVVM.Views
{
    [XamlCompilation(XamlCompilationOptions.Compile)]
    public partial class CoffeeEquipmentPage : ContentPage
    {
        public CoffeeEquipmentPage()
        {
            InitializeComponent();
            BindingContext = this;
        }

        int count = 0;
        private string countDisplay = "Click Me";
        public string CountDisplay
        {
            get { return countDisplay; }
            set
            {
                if (value == countDisplay)
                    return;

                countDisplay = value;
                OnPropertyChanged();
            }
        }

        private void btnCount_Clicked(object sender, EventArgs e)
        {
            count++;
            CountDisplay = $"You clicked {count} time";
        }
    }
}

Pada kode dibawah ini, kita akan menggunakan object Command untuk membinding proses penekanan tombol.. Modifikasi kode sebelumnya pada XAML Page.

    <Grid RowDefinitions="*,Auto,Auto,*">
        <Label Grid.Row="1" HorizontalOptions="Center"
               FontSize="Large" Text="{Binding CountDisplay}" />
        <Button 
            Command="{Binding IncreaseCount}" Grid.Row="2" Text="Click Me" />
    </Grid>

Kemudian pada code behind tambahkan kode berikut. Object Command akan dibinding kedalam button control. Object command sendiri akan digunakan untuk memanggil method OnIncrease untuk mengubah nilai variabel count. Class ini juga harus diturunkan dari BindableObject agar dapat menggunakan  objek OnPropertyChanged() untuk memberi tahu ke UI (form) ada perubahan pada property CountDisplay, sehingga nilai label di form juga ikut berubah.

        public CoffeeEquipmentPage()
        {
            InitializeComponent();
            IncreaseCount = new Command(OnIncrease);
            BindingContext = this;
        }

        private void OnIncrease()
        {
            count++;
            CountDisplay = $"You clicked {count} time";
        }

        public ICommand IncreaseCount { get; }

        int count = 0;
        private string countDisplay = "Click Me";
        public string CountDisplay
        {
            get { return countDisplay; }
            set
            {
                if (value == countDisplay)
                    return;

                countDisplay = value;
                OnPropertyChanged();
            }
        }
    }

Anda juga dapat memisahkan class ViewModel kedalam folder tersendiri agar lebih mudah untuk dimaintain. Buat folder ViewModel untuk menambahkan semua class viewmodel yang akan dibinding kedalam view. Pada ViewModel tambahkan class CoffeeEquipmentViewModel.cs, kemudian pindahkan kodenya.

    public class CoffeeEquipmentViewModel : BindableObject
    {
        public ICommand IncreaseCount { get; }
        public CoffeeEquipmentViewModel()
        {
            IncreaseCount = new Command(OnIncrease);
        }

        int count = 0;
        private string countDisplay = "Click Me";
        public string CountDisplay
        {
            get { return countDisplay; }
            set
            {
                if (value == countDisplay)
                    return;

                countDisplay = value;
                OnPropertyChanged();
            }
        }

        private void OnIncrease()
        {
            count++;
            CountDisplay = $"You clicked {count} time";
        }
    }

Kemudian pada XAML tambahkan kode berikut. Pada XAML dapat ditambahkan namespace viewmodels yang dapat digunakan secara deklaratif pada XAML.

<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
             xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml" 
             xmlns:viewmodels="clr-namespace:SampleMVVM.ViewModels"
             x:Class="SampleMVVM.Views.CoffeeEquipmentPage"
             x:DataType="viewmodels:CoffeeEquipmentViewModel">
    <ContentPage.BindingContext>
        <viewmodels:CoffeeEquipmentViewModel/>
    </ContentPage.BindingContext>
    
    <Grid RowDefinitions="*,Auto,Auto,*">
        <Label Grid.Row="1" HorizontalOptions="Center"
               FontSize="Large" Text="{Binding CountDisplay}" />
        <Button 
            Command="{Binding IncreaseCount}" Grid.Row="2" Text="Click Me" />
    </Grid>
</ContentPage>

Pada blog selanjutnya akan dibahas bagaimana cara menggunakan MVVM Helper untuk mempermudah bekerja dengan MVVM di Xamarin Forms.

Global Azure 2021 Indonesia

JIka pada tahun-tahun sebelumnya Global Azure 2021 dilaksanakan di berbagai kota seperti Yogyakarta, Bandung, Jakarta, dan Purwokerto. Maka tahun ini secara serempak Microsoft MVP melaksanakan bersama-sama secara daring di Indonesia. Kegiatan ini dimulai pada tanggal 17 April 2021 mulai pkl 09.15 – 15.45 melalui Microsoft Teams. Kegiatan ini dikelola secara volunteer oleh Microsoft User Group Indonesia – Purwokerto. Kegiatan ini mengundang 8 pembicara, satu perwakilan Microsoft Indonesia dan tujuh adalah Microsoft MVP. 

Berikut adalah daftar tema dan speaker pada Global Azure 2021. 

  • Kiki Rizki Noviandi: Database as Cloud Computing in Azure
  • Andri Yadi: Stay Awesome at Home with Smart Home, Powered by Azure
  • Erick Kurniawan: Architect API integration in Azure
  • Agus Suparno: Azure Cognitive Service
  • Ridi Ferdiana: 10 Tips to make your cloud cheaper
  • Agus Kurniawan: Containerize Your Applications to Microsoft Azure Kubernetes Service
  • Eriawan Kusumawardhono: DevOps everywhere using Azure DevOps on Azure

Pada event ini saya berkesempatan untuk membawakan topik tentang Architect API integration in Azure. Pada sesi ini didemokan bagaimana cara menggunakan Azure API Management yang ada di Azure sebagai API Gateway dari berbagai macam services yang ada pada Azure.