The Power of Refactoring

Project yang sedang dikerjakan sekarang adalah membuat Mobil App untuk membaca score (notasi musik) dengan beberapa fitur seperti pengaturan tempo, looping, environment, change instrument, adding annotation dan sebagainya. Masalahnya kemudian,hampir semua developer yang terlibat adalah backend programmer yang tidak punya pengalaman mengerjakan mobile app dan juga tidak familiar menggunakan pattern MVVM. Ya, projectnya menggunakan Xamarin dan MvvmCross framewrok.

Nah, pada sprint kesekian project pengerjaan projectnya semakin melambat. Salah satu penyebabnya adalah beberapa task mengharuskan menunggu pengerjaan developer yang lain karena mengharuskan bekerja pada class/module yang sama. Begitu juga bagian FrontEnd mengaku kesulitan dalam mengintegrasikan designnya karena harus bersentuhan dengan code program yang berhubungan dengan funcionality.

Akhirnya diputuskan dalam satu sprint di adakan refactor besar-besaran, tidak ada penambahan fitur. Refacor focus pada aspek Single Responsibility dan Separation of Concern. Juga melengkapi unit testing sehingga dapat dengan mudah dideteksi mana code yang termasuk smell code. Ya, salah satu tandanya adalah jika code tersebut tidak testable. Ternyata setelah mengadakan refactor yang cukup signifikan, Sprint berikutnya pekerjaan menjadi lebih mudah dan cepat.

Error When Call IMvxCommand in Unit Testing

Kode unit testing di bawah ini ketika memanggil SampleClickCommand menyebabkan error Null Object Reference.

[TestMethod]
       public void WhenPlayClick_SampleMusicIsPlaying()
       {
           _mockAudioService.Setup(arg => arg.PlayMusic(It.IsAny<string>()));
           _mockAudioService.Setup(arg => arg.IsMusicPlaying).Returns(true);
           _scoreLibraryCellViewModel = new ScoreLibraryCellViewModel(_mockAudioService.Object, _mockFileAccessService.Object, _mockDialogService.Object);
           _scoreLibraryCellViewModel.SampleClickCommand.Execute();
 
 
 
       }

Untuk meresolve error ini register type untuk IMvxStringToTypeParser saat initialisasi.

var ioc = MvxSimpleIoCContainer.Initialize();
          ioc.RegisterSingleton<IMvxStringToTypeParser>(new MvxStringToTypeParser());

 

How to update ObservableCollection in MvvmCross when property of Item is changes

Ketika develop android app menggunakan Xamarin. Saya menggunakan MvvmCross sebagai framework. Dalam MvvM patterna kita akan selalu berurusan dengan Binding data antara View(UI)- dan ViewModel.

Saat saya melakukan binding data ObservableColletion pada ViewModel dengan ListView pada View ternyata event Collection Changes pada ObservableCollection tidak di rise ketika ada perubahan pada property di itemnya. Jadi setelah saya baca-baca, event Collection Changes ini hanya di rise ketika ada penambahan atau pengurangan jumlah item pada ObservableCollection.

Layout View.

 
 

ViewModel:

ProductListItemViewModel:

public class ProductListItemViewModel : MvxViewModel
   {
       
       public int Id { get; set; }
 
       public string Name { get; set; }
 
       private decimal _quantity;
 
       
       public decimal Quantity
       {
           get
           {
               return _quantity;
 
           }
           set
           {
               _quantity = value;
               RaisePropertyChanged(() => Quantity);
               
           }
       }

ProductListViewModel.

private ObservableCollection _displayedProducts;
       public ObservableCollection DisplayedProducts
       {
           get { return _displayedProducts; }
           set
           {
               _displayedProducts = value;
               RaisePropertyChanged(() => DisplayedProducts);
               Calculate();
           }
       }
       private void Calculate()
       {
           decimal totalSales = 0;
           decimal totalGst = 0;
           foreach (var product in DisplayedProducts)
           {
               var sales = (product.Price * product.Quantity);
               totalSales += sales;
               if (product.GstFlag)
               {
                   totalGst += sales * Utility.Constants.GST_RATE;
               }
           }
           TotalSales = totalSales;
           TotalGst = totalGst;
       }
       private decimal _totalSales;
       public Decimal TotalSales
       {
           get
           {
               
               return _totalSales;
           }
           set
           {
               _totalSales = value;
               RaisePropertyChanged(() => TotalSales);
           }
           
       }
       private decimal _totalGst;
       public Decimal TotalGst
       {
           get
           {
 
               return _totalGst;
           }
           set
           {
               _totalGst = value;
               RaisePropertyChanged(() => TotalGst);
           }
 
       }

Karena saya ingin ketika ada perubahan quantity pada Product (inputnya ditrigger dari editable text field pada listview), calculate() method dipanggil lagi sehingga property TotalSales dan TotalGst akan diupdate otomatis.

Saya menemukan solusinya dengan menset event PropertyChanges pada ProductListItemViewModel sebelum menambahkannya pada ObservableCollection seperti ini.

productViewItemModel.PropertyChanged += ProductViewItemModel_PropertyChanged;
               productViewModels.Add(productViewItemModel);
private void ProductViewItemModel_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            Calculate();
        }

code lengkapnya ada di https://github.com/adnansetiawan/sales-app-xamarin

Builder Pattern

Jika kita memiliki sebuah class dengan banyak argument pada konstruktornya, kita bisa mempertimbangkan menggunakan Builder Pattern. Sebagai contoh

 

public Employee(string name, string carName, int paySheet, int carPrice, int saving, decimal monthlySaving,
           ITaxPaymentService taxPaymentService)
       {
           _name = name;
           _carName = carName;
           _paySheet = paySheet;
           _carPrice = carPrice;
           _saving = saving;
           _monthlySaving = monthlySaving;
           _taxPaymentService = taxPaymentService;
 
       }

kita bisa membuat sebuah class builder seperti ini.

 

public class EmployeeParam
   {
       
       public string Name { get; private set; }
       public int CarPrice { get; private set; }
       public string CarName { get; private set; }
       public int Saving { get; private set; }
       public decimal MonthySaving { get; private set; }
       public int PaySheet { get; private set; }
 
       public class Builder
       {
           private string _name;
           private int _carPrice;
           private string _carName;
           private decimal _monthySaving;
           private int _paySheet;
           private int _saving;
 
           public Builder WithName(string value)
           {
               _name = value;
               return this;
           }
 
           public Builder WithCarName(string value)
           {
               _carName = value;
               return this;
           }
 
           public Builder WithCarPrice(int value)
           {
               _carPrice = value;
               return this;
           }
 
           public Builder WithPaySheet(int value)
           {
               _paySheet = value;
               return this;
           }
 
           public Builder WithSaving(int value)
           {
               _saving = value;
               return this;
           }
 
           public Builder WithMonthlySaving(int value)
           {
               _monthySaving = value;
               return this;
           }
 
           public EmployeeParam Build()
           {
               return new EmployeeParam
               {
                   Name = _name,
                   CarName = _carName,
                   CarPrice = _carPrice,
                   MonthySaving = _monthySaving,
                   PaySheet = _paySheet,
                   Saving = _saving
               };
           }
       }
   }

 

Sekarang kita bisa memanggil class Employee dengan lebih readable seperti ini.

 

var richManBuilder = new EmployeeParam.Builder()
              .WithName("Rikki")
              .WithCarName("BMW")
              .WithPaySheet(40000000)
              .WithCarPrice(400000000)
              .WithSaving(120000000)
              .WithMonthlySaving(15000000)
              .Build();

 

Employee = new Employee(richManBuilder, _taxPaymentService);

 

 

Multi-Layer Arsitektur Menggunakan .Net Framework

Memenuhi salah satu resolusi saya tahun ini  yaitu belajar menulis buku, saya menyempatkan waktu untuk menulis di setiap akhir pekan. Setelah beberapa bulan,  akhirnya selesai juga buku yang sangat sederhana ini.

Buku kecil ini membahas tentang bagaimana menulis kode yang bersih, mudah di maintenance dan ditest dalam arsitektur N-tier klasik (Data Layer, Bussiness Logic Layer, dan Presentation Layer) dalam contoh yang sederhana. Dalam buku ini juga disertai contoh menulis unit test untuk tiap layer aplikasinya. Harapan saya semoga buku ini bermanfaat.

book_cover

Daftar isi.

daftar_isi_1daftar_isi_2

Bagi yang tertarik, silahkan tulis emailnya di form di bawah ini. Kenapa gak langsung saja? Soalnya saya butuh tahu siapa dan berapa orang yang membaca buku ini. Tak perlu bayar alias gratis, tapi kalau mau donasi juga gak apa-apa :D. Tolong untuk tidak didistribusikan demi keuntungan materi.

.Net Rasa NodeJs menggunakan Nancy

Setelah membaca beberapa tulisan mengenai Microservices yang banyak menggunakan Nancy. Saya jadi kepengen cari tahu Nancy itu seperti apa. Sekilas yang saya baca, Nancy ini terinspirasi dari kesederhanaan salah satu framework Ruby yaitu Sinatra. Nancy membuat kita bisa membuat sebuah Rest Api tanpa harus menggunakan Web Api pada .Net sehingga menjadi lebih sederhana dan mudah. Menurut saya sih, mirip ketika kita membuat Rest Api menggunakan NodeJs. Sebagai contoh kita membuat sebuah Nancy service yang running pada http://localhost:8888.

class Program
    {
        static void Main(string[] args)
        {
            var url = "http://localhost:8888";
 
            using (var host = new NancyHost(new Uri(url)))
            {
                host.Start();
                Console.WriteLine($"Listening in {url}");
                Console.ReadLine();
            }
        }
    }

nancy_app

Sekarang kita buat sebuat routing menggunakan NancyModule.

public class NancyMicroservices : NancyModule
    {
        public NancyMicroservices()
        {
            Get["angles"] = parameters =>
            {
                var angles = new object []
                {
                    new {
                        Name = "Raisa",
                        Occupation = "Singer"
                    },
                    new {
                        Name = "Isyana",
                        Occupation = "Singer"
                    },
 
                };
 
                return Response.AsJson(angles);
            };
 
        }

Buka browser :

nancy_response.png