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

Binding ListView using MvvmCross in Xamarin

Melanjutkan project pada tulisan MVVM Pattern in Xamarin Project using MvvmCross.

Kita buat sebuah class Book di Portable project.

public class Book
{
public int Id { get; set; }
public string Title { get; set; }
public string Image { get; set; }
public string Author { get; set; }
public decimal Price { get; set; }
public int Year { get; set; }
}

Kemudian kita buat lagi sebuah ViewModel. ViewModel yang digunakan pada ListView harus berisi setidaknya sebuah ObservableCollection. Di konstruktor kita inisialisasi data untuk ObservableCollection Items.

public class BookViewModel : MvxViewModel
{
public ObservableCollection Items { get; set; }
public BookViewModel()
{
Items = new ObservableCollection();
Items.Add(
new Book
{
Id = 1,
Title = "Lord Of The Ring",
Author = "JJR. TOLKIEN",
Price = 40,
Year = 2001,
Image = "https://luckty.files.wordpress.com/2012/05/b32.jpg"
});
Items.Add(
new Book
{
Id = 2,
Title = "The Hobbit",
Author = "JJR. TOLKIEN",
Price = 35,
Year = 2014,
Image = "https://images-na.ssl-images-amazon.com/images/I/41aQPTCmeVL._SX331_BO1,204,203,200_.jpg"
});

}
}

Selanjutanya pada project .Droid (android) kita buat sebuah Layout (.axml), sebagai contoh kita beri nama BookListView.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Mvx.MvxListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        local:MvxItemTemplate="@layout/row_layout"
        local:MvxBind="ItemsSource Items">
</LinearLayout>

Perhatikan local:MvxBind=”ItemsSource Items”, artinya kita melakukan Binding data pada ListView dari property Items pada class Book. Sedangkan  untuk menentukan template pada ListView kita gunakan  local:MvxItemTemplate.

Pada folder Layout buat sebuah AndroidLayout (.axml) dengan nama row_layout.

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:padding="8dp">
    <LinearLayout
        android:id="@+id/Text"
        android:orientation="vertical"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:paddingLeft="10dip">
        <TextView
            android:id="@+id/Text2"
            android:layout_width="wrap_content"
            android:layout_height="15.0dp"
            android:textSize="14dip"
            android:paddingLeft="100dip"
            local:MvxBind="Text Title" />
    </LinearLayout>
    <Mvx.MvxImageView
        android:layout_width="78.0dp"
        android:layout_height="82.5dp"
        android:padding="5dip"
        local:MvxBind="ImageUrl Image" />
</RelativeLayout>

Perhatikan kita melakukan binding Image dengan menggunakan; ItemLongClick ShowInfo”local:MvxBind=”ImageUrl Image” yang artinya ImageUrl pada grid di set dari properti Image pada class Book.

Selanjutnya kita buat sebuah activity yang merupakan turunan dari  MvxActivity kemudian pada generic parameternya kita set model yang akan dipanggil yaitu BookViewModel. Jangan lupa set content viewnya dari Layout BookListView.

[Activity(Label = "Book List", MainLauncher = true)]
public class BookView : MvxActivity<BookViewModel>
{
protected override void OnViewModelSet()
{
base.OnViewModelSet();
SetContentView(Resource.Layout.BookListView);
}
}

Kita running emulator android kita

mvvm_book_emulator.png

Sekarang kita tambahkan event ketika ListView item di click dengan agak lama. Event ini akan memunculkan user dialog alert info tambahan dari Book. Kita tambahkan sebuah ICommand property pada class Book.

public ICommand ShowInfo
{
get
{
return new MvxCommand(b => Mvx.Resolve().Alert(GetInfo(b)));
}

}

protected string GetInfo(Book book)
{
var output = new StringBuilder();
output.Append($"Author: {book.Author}");
output.AppendLine();
output.Append($"Year: {book.Year}");
output.AppendLine();
output.Append($"Price: {book.Price}");
return output.ToString();
}

ShowInfo kita bind sebagai event ketika ListView item click sehingga layout dari BookListView jadi seperti ini.

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res-auto"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <Mvx.MvxListView
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        local:MvxItemTemplate="@layout/row_layout"
        local:MvxBind="ItemsSource Items; ItemLongClick ShowInfo" />
</LinearLayout>

Untuk UserDialog kita menggunakan plugin ACR User Dialogs. Install lewat Nuget package manager console.

PM > Install-Package Acr.UserDialogs

Jangan lupa pada class App.cs di .Portable project register instance dari IUserDialog.

Mvx.RegisterSingleton(UserDialogs.Instance);

_user_dialog_xamarin.png

MVVM Pattern in Xamarin Project using MvvmCross

Salah satu jenis pattern yang sering digunakan pada pengembangan aplikasi dekstop dan mobile dalah Model-View View Model. Seperti pattern MVC, MVVM juga memisahkan application logic dan User Interface sehingga aplikasi akan lebih mudah ditest, dimaintenance  dan dikembangkan.

Ada 3 komponen yaitu: model, view dan view model. Masing-masing memiliki peran dan tanggung jawab yang berbeda seperti diilustrasikan pada gambar berikut ini.

ic564167

Kita akan membuat project sederhana menggunakan Xamarin. Pilih Cross-Platform->Portable project

mvvmcross1

Kita akan melihat ada 3 project, portable, android dan ios.

MvvmCross2.png

Kita akan rename BookStoreMvvm.Core.Droid menjadi BookStoreMvvm.UI.Droid. Selanjutnya lewat nuget, install MvvmCross.Core

MvvmCross4.png

Pada project .Portable kita buat sebuah interface untuk service.

public interface ICalculatorService
{
int Add(int number1, int number2);
}

Kemudian class Implementasinya.

public class CalculatorService : ICalculatorService
{
public int Add(int number1, int number2)
{
return number1 + number2;
}
}

Sekarang kita buat sebuah class View Model yang inherit dari class MvxViewModel, karena dalam MvvmCross semua View Model harus merupakan class turunan dari MvxViewModel.

public class CalculatorViewModel : MvxViewModel
{
ICalculatorService _calculatorService;
public CalculatorViewModel(ICalculatorService calculatorService)
{
_calculatorService = calculatorService;
}
public override void Start()
{
Add();
base.Start();
}

int _operand1;
public int Operand1
{
get { return _operand1; }
set
{
_operand1 = value;
Add();

}
}

int _operand2;
public int Operand2
{
get { return _operand2; }
set
{
_operand2 = value;
Add();

}
}
int _result;
public int Result
{
get { return _result; }
set {
_result = value;
RaisePropertyChanged(() => Result);
}
}

private void Add()
{
Result = _calculatorService.Add(_operand1, _operand2);
}
}

RaisePropertyChanged(), artinya kita memberikan notifikasi bahwa sebuah property telah berubah sehingga pada UI nilainya akan disesuaikan dengan perubahan. Jadi sini, jika property Result di set pada setiap pemanggilan method Add(), maka nilai result pada UI akan ikut berubah.

Karena pada class di atas kita menggunakan dependency injection -yaitu dengan melewatkan tipe ICalculatorService pada konstruktor, kita perlu meregistrasi interface dan class implementasinya disebuah class App. Class App ini juga akan menentukan ViewModel mana yang akan digunakan saat Start.

public class App : MvxApplication
{
public App()
{
Mvx.RegisterType<ICalculatorService, CalculatorService>();
Mvx.RegisterSingleton(new MvxAppStart());
}
}

Selanjutnya pada project .Droid kita hapus MainActivity dan Main.axml. Kita tidak membutuhkan file-file itu lagi.

mvvm_34.png

Selanjutnya buatlah class Setup untuk melakukan inisialiasi framework MvvmCross pada project android kita. Untuk android, class Setup harus merupakan turunan dari MvxAndroidSetup.

public class Setup : MvxAndroidSetup
{
public Setup(Context applicationContext) : base(applicationContext)
{
}

protected override IMvxApplication CreateApp()
{
return new App();
}
}

Kemudian kita buat sebuah layout (.axml) seperti ini.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:local="http://schemas.android.com/apk/res/BookStoreMvvm.UI.Droid"
    android:orientation="vertical"
    android:layout_width="match_parent"
    android:layout_height="match_parent">
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        local:MvxBind="Text Operand1" />
    <EditText
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        local:MvxBind="Text Operand2" />
    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        local:MvxBind="Text Result" />
</LinearLayout>

local:MvxBind artinya field ui yang kita buat akan melakukan binding dengan property sebuah ViewModel.

Selanjutanya kita buat sebual class view (kalau pada Xamarin Form kita menyebutnya Activity), yang merupakan turunan dari MvxActivity. Kita tambahkan attribut activity sebagai main launcer agar class ini diekseskusi sebagai main activity.

[Activity(Label = "Calculator", MainLauncher = true)]
public class CalculatorView : MvxActivity
{
public new CalculatorViewModel ViewModel
{
get { return (CalculatorViewModel)base.ViewModel; }
set { base.ViewModel = value; }
}

protected override void OnViewModelSet()
{
base.OnViewModelSet();
SetContentView(Resource.Layout.Calculator);
}
}

Kita running android project kita.mvvm_show.png

Selanjutnya kita  ganti nilai dari field pertama (binding : Operand1) dan kedua(binding: Operand2). Terlihat bahwa nilai field ketiga(binding:Result) nilainya merupakan nilai penambahan field pertama dan kedua.

mvvm_show1.png

Menulis Buku Pemrograman

Salah satu resolusi saya tahun ini selain hidup lebih sehat dan mengurangi menatap layar gadget di rumah, adalah menulis buku. Setelah tiga bulan menulis sedikit demi sedikit di akhir pekan, sekarang progressnya sudah mencapai 80%.

Saya menulis buku berawal dari melihat kurangnya buku pemrograman di Indonesia yang membahas hal-hal yang konseptual seperti prinsip-prinsip menulis dan mendesain program yang baik. Walaupun saya tahu, saya harus masih banyak belajar lagi mengenai topik itu. Ya anggaplah, buat pemacu belajar juga. Semakin kita bisa menjelaskan sesuatu secara sederhana, semakin kita mengerti apa yang kita sampaikan.

Jujur saya gak bisa mendesign, jadi saya pakai template yang ada di MS Office aja. Anggap saja cover buku sementaras selagi menunggu ada yang berbaik hati mendesignkan cover bukunya :). Semoga bulan depan sudah bisa direlease.

cover_book

 

Yang sering diabaikan, Non-functional Requirement

Ketika terlibat dalam sebuah team project pengembangan perangkat lunak, kita sebagai developer seringkali terlalu focus pada low level detail  sehingga lupa melihat big-picture berupa non-functional requirement seperti performance, scalability, availability dan security.

Performance

Performance bicara tentang seberapa cepat aplikasi tersebut, biasanya kita menggunakan term response time atau latency.Response time adalah waktu yang dibutuhkan antara sebuah request dikirim dan response diterima secara penuh. Seperti ketika kita menekan tombol hyperlink pada sebuah halaman web dan menunggu halaman page tersebut di load secara keseluruhan. Sedangkan latency adalah waktu yang diperlukan sebuah pesan untuk berpindah dalam sebuah system, dari suatu titik ke titik yang lain. Latency mengukur berapa besar waktu ketika response baru saja diterima. Sehingga Response Time akan selalu lebih besar daripada Latency.

Scalability

Scalability pada dasarnya kemampuan software untuk menangani lebih banyak pengguna, request, data dan sebagainya dalam periode waktu yang sama, misalanya berapa request per second.

Availability

Availability adalah tentang bagaimana tingkat ketersediaan (available) software untuk menangani request.  Biasanya diukur menggunakan terminasi “nines”. Seperti 99,99% (four nine) atau 99,999% (five nine).Angka-angka tersebut adalah angka uptime yang menunjukan berapa besar jumlah downtime yang bisa ditoleransi. Contoh, 99.9% (three nines) artinya downtime berkisar hanya 1 menit per harinya yang digunakan untuk jadwal maintenance berkala, upgrade atau memang terjadi kesalahan yang tidak diharapkan.

Security

Security berkaitan dengan segala sesuatu dari authentikasi dan authorisasi sampai pada bagaimana data tersebut disimpan. Authentikasi adalam proses memverifikasi user lewat credential yang dikirim. Sedangkan authorisasi terjadi setelah authentikasi, untuk membatasi resource mana yang boleh diakses oleh user  (file, url dan sebagainya).

Audit

Seringkali kita butuh untuk menyimpan log sebuah event yang bisa membantu kita untuk melakukan pelacakan perubahan sebuah data dari software system, terutama yang menyangkut transaksi yang melibatkan “uang”.  Bisanya sih disebut Audit Trail, dimana kita menyimpan data siapa yang melakukan perubahan, kapan perubahan itu terjadi dan apa saja yang berubah record yang berubah.

 

Flexibility

Flexibility adalah mengenai bagaimana software yang kita bangun memudahkan non-techincal user untuk memodifikasi business rules yang ada pada software. Sebagai contoh, kita bisa memasukkan value-value yang gampang dikonfigurasi di database ataupun diset lewat file configurasi seperti connection string, base url address, smpt server dan sebagainya.

Dan masih ada beberapa hal yang lain lagi seperti Maintability, Legal dan Localization..

 

 

 

 

Reflection – Printing Property Value Of Object

Anggaplah kita mempunya sebuah class Person seperti ini.

public class Person
{
public Person()
{
Childs = new List();
}
public string Name { get; set; }
public int Age { get; set; }
public Address PostalAddress { get; set; }
public Person Parent { get; set; }
public List Childs { get; set; }

}

public class Address
{
public string Street { get; set; }

}

Kita ingin mencetak seluruh property yang tidak null dari object Person di atas termasuk object dan collection yang ada di dalamnya menggunakan reflection.

private static void PrintProperties(object obj, int indent)
{
if (obj == null) return;
string indentString = new string(' ', indent);
Type objType = obj.GetType();
PropertyInfo[] properties = objType.GetProperties();
foreach (PropertyInfo property in properties)
{
object propValue = property.GetValue(obj, null);
var elems = propValue as IList;
if (elems != null)
{
if (elems.Count > 0)
{
Console.WriteLine("{0}{1}:", indentString, property.Name);
foreach (var item in elems)
{
PrintProperties(item, indent + 3);
}
}
}else
{
if (property.PropertyType.Assembly == objType.Assembly)
{
if (propValue != null)
{
Console.WriteLine("{0}{1}:", indentString, property.Name);
PrintProperties(propValue, indent + 2);
}
}else
{
Console.WriteLine("{0}{1}: {2}", indentString, property.Name, propValue);
}
}
}
}

var child1 = new Person() { Name = "Abe", Age = 1 };
var child2 = new Person() { Name = "Lisa", Age = 5 };
var parent = new Person()
{
Name = "Me",
Age = 40,
PostalAddress = new Address
{
Street = "Bandung Soekarno Hatta"
}
};
parent.Childs.Add(child1);
parent.Childs.Add(child2);
PrintProperties(parent, 1);

Ketika dijalankan, hasilnya seperti ini:

reflection

Automapper and Entity Framework Query Performance

Ketika kita membuat sebuah aplikasi dengan arsitektur N-layer, dimana object entities dari Data Access Layer dimapping menggunakan AutoMapper terhadap object Dto pada Business Layer. Mapping tersebut perlu kita perhatikan, terutama jika kita menggunakan lazy loading pada Entity Framework sebagai ORM dan navigasi properties yang kita mapping adalah collection.

public class Price
{
public Price()
{
this.Benefits = new HashSet();
this.PriceCalculates = new HashSet();
}

public int Id { get; set; }
public string Name { get; set; }
public virtual PriceTemplate PriceTemplate { get; set; }
public virtual ICollection Benefits { get; set; }
public virtual ICollection PriceCalculates { get; set; }
}
public class PriceDto
{
public PriceDto()
{
this.BenefitIds = new List();
this.PriceCalculates = new List();
}

public int Id { get; set; }
public string Name { get; set; }
public PriceTemplate PriceTemplate { get; set; }
public List BenefitIds { get; set; }
public List PriceCalculates { get; set; }
}

Contoh, kita meregistrasi mapping antara class Price entities dengan class PriceDto sebagai object Dto.

CreateMap<Price, PriceDTO>()
.ForMember(dest => dest.PriceCalculates, opt => opt.Ignore())
.ForMember(dest => dest.BenefitsId,
opt => opt.MapFrom(src => src.Benefits.Select(benefit => benefit.Id).ToList()))
.IgnoreAllNonExisting();

Ternyata sesuai requirement pada tampilan list aplikasi kita, kita tidak perlu menampilkan data PriceCalculates. Hanya perlu ditampilkan pada form detail saja.

Jika generic repository kita menggunakan lazy loading, maka akan ada hit ke database sebanyak jumlah data yang ditampilkan. Untuk menghindari issue tersebut,Ignore mapping semua navigation properties yang tidak digunakan pada Dto. Kenapa perlu diignore secara explisit padahal sudah menggunakan extension .IgnoreAllNonExisting() ? karena secara default automapper akan melakukan mapping jika property class sumber dan destinasi namanya sama (tidak case sensitif).

CreateMap<Price, PriceDTO>()
.ForMember(dest => dest.PriceCategories, opt => opt.Ignore())
.ForMember(dest => dest.PriceCalculates, opt => opt.Ignore())
.ForMember(dest => dest.BenefitsId,
opt => opt.MapFrom(src => src.Benefits.Select(benefit => benefit.Id).ToList()))
.IgnoreAllNonExisting();

Perhatikan, kita tetap butuh map dari navigaiton property Benefits pada Price terhadap property BenefitsId. Agar data Benefits diambil sekaligus pada saat melakukan query Price, tambahkan sebagai include properties

var includedProperties = "Benefits";
var prices = _priceRepo.Get(filter, orderBy, includedProperties);

sebagai tambahan, implementasi dari method Get pada Price Repository di atas (_priceRepo) seperti berikut ini, lihat Generic Repository Entity Framework Part I

public virtual IEnumerable Get(
Expression<Func<Class, bool>> filter = null,
Func<IQueryable, IOrderedQueryable> orderBy = null,
string includeProperties = "")
{
IQueryable query = dbSet;

if (filter != null)
{
query = query.Where(filter);
}

foreach (var includeProperty in includeProperties.Split
(new char[] { ',' }, StringSplitOptions.RemoveEmptyEntries))
{
query = query.Include(includeProperty);
}

if (orderBy != null)
{
return orderBy(query).ToList();
}
else
{
return query.ToList();
}
}