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();
}
}

Assembly Loader Error

System.IO.FileLoadException: Could not load file or assembly ‘NLog, Version=2.1.0.0, Culture=neutral, PublicKeyToken=5120e14c03d0593c’ or one of its dependencies. The located assembly’s manifest definition does not match the assembly reference. (Exception from HRESULT: 0x80131040)

Jika suatu saat anda mendapat error seperti di atas, artinya assembly loader tidak menemukan assembly yang di reference. Ternyata untuk kasus saya, di app.config ternyata mereference assembly version yang berbeda.

<dependentAssembly>
    <assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="4.0.0.0" />
 </dependentAssembly>

Ada 2 cara untuk menyelesaikan issue ini.

  1. hapus configurasi tersebut di app.config
  2. Kita paksa untuk semua version tertentu dalam kasus ini versi .4.0.0.0 di redirect ke version 2.1.0.0.
<dependentAssembly>
     <assemblyIdentity name="NLog" publicKeyToken="5120e14c03d0593c" culture="neutral" />
     <bindingRedirect oldVersion="0.0.0.0-4.0.0.0" newVersion="2.1.0.0" />
</dependentAssembly>

 

Pemrograman Beriorentasi Object Menggunakan Javascript (Part II)

  1. Menggunakan Module Pattern Object Literal

Object Literal digambarkan dalam kumpulan comma-separated name/value pairs yang diapit oleh curly braces ({}). Object literal tidak memerlukan instanisasi.

ar myObjectLiteral = {

variableKey: variableValue,

functionKey: function () {
// ...
}
};

var personModule = {

name: "nila",

// object literals can contain properties and methods.
// e.g we can define a further object for module configuration:
dob: {
place: "campalagian",
date: "10-10-1990"
},

// a very basic method
saySomething: function () {
console.log( "hello!!" );
},

// output a value based on the current configuration
showName: function () {
console.log( "my name is " + this.name );
},

// override the current configuration
updateDob: function( newDob ) {

if ( typeof newDob  === "object" ) {
this.dob = newDob;
console.log( this.dob.place);
}
}
};

// Outputs: hello!!
personModule.saySomething();

// Outputs: my name is nila
personModule.showName();

// Outputs: semarang
personModule.updateDob({
place: "semarang",
date: "10-10-1990"
});

Pemrograman Beriorentasi Object Menggunakan Javascript (Part I)

Hampir semua programmer tidak asing dengan pradigma pemrograman beriorentasi object (OOP), jadi tidak perlu saya jelaskan lagi di sini. Kebanyakan bahasa pengantar untuk mata kuliah OOP adalah java atau c++. Bagaimana dengan OOP menggunakan javascript??  yang terbiasa menggunakan javascript di sisi server seperti Node JS atau framework javascript di sisi client seperti AngularJS atau Backbone.Js tentu akan menjadi penting. Ok, mari kita mulai!..

  1. Menggunakan Prototype-based programming.

Javascript adalah sebuah prototype-based language, jadi kita tidak akan menemukan statement class seperti pada bahasa yang lain (Java, C++, C#..). Fungsi-fungsi pada Javascript memiliki property yang disebut “prototype”.  Berikut contoh membuat class menggunakan pendekatan Prototype.

function Person(name, age) {
 this.name = name;
 this.age = age;
}
Person.prototype = {
 getName: function() {
   return this.name;
},
 getAge: function() {
  return this.age;
}
}

instanisasi class person tersebut dengan cara seperti ini.

var alice = new Person('Alice', 93);
var bill = new Person('Bill', 30);
console.log(alice.getName()); //result is "Alice"
console.log(alice.getAge()); //result is "93"

Dengan mengakses prototype class person di atas bisa juga ditulis seperti ini:

Person.prototype.getName = function(){
return this.name;
};Person.prototype.getAge = function(){
return this.age;
};