Custom Configuration Handler

File configurasi baik itu app.config maupun web.config adalah file xml yang berisi configurasi external dari aplikasi yang kita buat. Seringkali kita melakukan pemanggilan nilai pada file configurasi seperti ini.

var baseUrl = ConfigurationManager.AppSettings["BaseUrl"].ToString();

Semakin kompleks aplikasi, terkadang membuat bertambahnya nilai yang perlu di store di configurasi. Supaya configurasi kita mudah di maintenance jika ada perubahan key pada configurasi dan menghindari kesalahan pengetikan pada key, kita bisa membuat class untuk menghandle issue tersebut.

public class BLLConfiguration : ConfigurationSection
{
public string BaseUrl { get; set; }
public static BLLConfiguration GetConfig()
{
var section = ConfigurationManager.GetSection("Astral/BusinessLogic");
if (section == null)
throw new ConfigurationErrorsException(
ErrorMessages.ConfigurationErrorsException);

return (BLLConfiguration)ConfigurationManager.GetSection("Astral/BusinessLogic");
}

public void LoadConfigValues(XmlNode node)
{
var attributeCollection = node.Attributes;
if (attributeCollection["BaseUrl"] != null)
BaseUrl = attributeCollection["BaseUrl"].Value;
}
}

public class BLLConfigurationHandler : IConfigurationSectionHandler
{
public Object Create(Object parent, Object configContext, XmlNode node)
{
var config = new BLLConfiguration();
config.LoadConfigValues(node);
return config;
}
}

Pada web config/appconfig daftarkan section tersebut. Pada type, formatnya adalah {Namespace.ClassName},{AssemblyName}

custom_config.png

Kemudian, assign value pada confurasi dibuat dalam satu section berdasarkan pada nama sectionGroup dan section-nya.

custom_config_1.png

Pemanggilan value dari configurasi jadinya seperti ini.

var baseUrl = BLL.BLLConfiguration.GetConfig().BaseUrl;

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>

 

Mocking Unit Test Object Menggunakan NSubtitute

NSubtitute

http://nsubstitute.github.io/

Nsubtitute adalah salah satu mocking library untuk .NET yang memiliki configurasi yang sederhana sehingga mudah digunakan. NSubtitute di design untuk testing dengan pendekatan Arrange-Act-Assert (AAA), sehingga kita hanya butuh untuk mengatur bagaimana harusnya dia bekerja dan kemudian membuat pemanggilan Assertion.

Kita bisa menginstall NSubtitute lewat Packet Manager Console pada Visual Studio.

install-nsubtitute.png

Sebagai contoh kita akan membuat abstraksi operasi pada Calculator menggunakan interface.

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

Kemudian kita mempunyai sebuah class yang menyediakan service untuk menampilkan hasil kalkulasi tersebut. Prinsip dasar unit test adalah melakukan test pada unit terkecil dari kode program kita dan mengisolasi extenal class yang ada.

Karena kita akan membuat unit test untuk class CalculatorService, sehingga external class berupa class implentasi dari ICalculator kita buatkan mockup nya saja.

public class CalculatorService
   {
       private ICalculator _calculator;
       public CalculatorService(ICalculator calculator)
       {
           _calculator = calculator;
       }
       public int Add(int number1, int number2)
       {
           if (number2 == 0)
           {
               throw new Exception("Dived by Zero Exception, please input number2 != 0");
           }
           var result = _calculator.Add(number1, number2);
           return result;
       }
   }

Setiap class Unit Test haruslah ditandai dengan attribute [TestClass] dan Unit Test Method dengan attribute [TestMethod].

[TestClass]
public class CalculatorServiceTest
{
    [TestMethod]
    public void Add_ReturnValidResult()
    {
    }
}

Jika kita menginginkan suatu proses tertentu yang harus dilakukan sebelum unit test method dijalankan seperti proses inisialisasi data, kita bisa membuat method dengan attribute [TestInitialize] dan sebalikanya jika kita menginginkan sebuah proses yang dieksekusi setiap sebuah unit test method di jalankan kita bisa membuta method dengan attribute [TestCleanup].

[TestInitialize]
public void Setup()
{

}
[TestCleanup]
public void Cleanup()
{
}

Jika Kita melakukan test terhadap expection yang mungkin ada, tambahkan attribute [ExpectedException].

[TestMethod]
[ExpectedException(typeof(Exception))]
public void Add_WhenNumber2IsZeroReturnException()
{
}

Untuk melakukan mockup object, cukup dengan menulis kode seperti ini. Usahakan implementasi yang kita buat selalu berawal dari abstraksi sehingga memudahkan menulis kode mockup objectnya.
csharp _calculator = Substitute.For();

Selanjutnya kita akan memockup method Add pada ICalculator seperti ini.
csharp _calculator.Add(1, 2).Returns(3);

Bentuk class unit test selengkapnya sepert ini.

[TestClass]
    public class CalculatorServiceTest
    {
        private ICalculator _calculator;
        private CalculatorService _calculatorService;

        [TestInitialize]
        public void Setup()
        {
            _calculator = Substitute.For<ICalculator>();
            _calculatorService = new CalculatorService(_calculator);
        }
        [TestCleanup]
        public void Cleanup()
        {
            _calculator = null;
            _calculatorService = null;
        }

        [TestMethod]
        public void Add_ReturnValidResult()
        {
            var expectedResult = 3;
            ///arrange
            _calculator.Add(1, 2).Returns(expectedResult);
            ///act
            var actualResult = _calculatorService.Add(1, 2);
            ///assert
            Assert.AreEqual(expectedResult, actualResult);
        }
        [TestMethod]
        [ExpectedException(typeof(Exception))]
        public void Add_WhenNumber2IsZeroReturnException()
        {
            try
            {
                _calculatorService.Add(1, 0);
                Assert.Fail();
            }
            catch(Exception ex)
            {
                Assert.IsInstanceOfType(ex, typeof(Exception));
                Assert.AreEqual("Dived by Zero Exception, please input number2 != 0", ex.Message);
                throw ex;

            }
           
        }
    }

 

Mari kita jalankan class unit test kita.

pass-unit-test

Query menggunakan kondisi selisih DateTime pada Entity Framework

Tidak semua query pada Linq di support oleh Entity Framework, termasuk pengurangan 2 nilai datetime.

public List<Price> GetExpiredPrice()
{
   return _priceRepo.Get(x=>x.EndDate.Value.Subtract(DateTime.Now).Days == Core.Constants.PriceReminderDays).ToList();
}

Query di atas akan menghasilkan error

cannot be converted to SQL.

Gunakan DbFunctions dari  assembly System.Data.Entity

public List<Price> GetExpiredPrice()
{
    return _priceRepo.Get(x=>DbFunctions.DiffDays(DateTime.Now, x.EndDate) == Core.Constants.PriceReminderDays).ToList();
}

 

 

Perbedaan Asosiasi, Agregasi dan Komposisi pada Object Oriented Programming

Ketika kita membaca atau membuat diagram class UML, kita tidak pernah lepas dari relasi antar class. Seringkali membingungkan adalah bagaimana implementasi relasi tersebut dalam bentuk kode program.

Ada beberapa teknik yang digunakan jika berbicara mengenai relasi antar class yaitu:

Assosiation (Assosiasi)

Assosiasi adalah hubungan antara object. Relasi assosiasi biasa disebut is “a” relationship. Assosiasi berarti bahwa sebuah object “menggunakan” object yang lain. Assosiasi adalah sebuah relasi dimana semua object memiliki lifecycle nya sendiri dan tidak ada yang bertindak sebagai owner.

Contoh Teacher dan Student. Banyak Student dapat berasosiasi dengan satu Teacher dan satu Student   dapat berasosiasi dengan banyak Teacher. Object keduanya bisa dibuat dan dihancurkan secara mandiri tanpa berpengaruh pada eksistensi object lain.

Aggregation (Agregasi)

Agregasi adalah bentuk hubungan yang lebih khusus dari Assosiasi dimana sebuah object memiliki lifecycle nya sendiri tapi dengan kepemilikan dan class child tidak dapat memiliki class parentnya. Relasinya biasa di sebut relasi “has-a”.

Sebagai contoh, Department dan Teacher. Satu Teacher tidak dapat memiliki banyak Department, tapi jika kita menghapus object Department, object Teacher tidak akan ikut terhapus. Contoh:

public class Department
    {
        private string _name;

        public Department(string name)
        {
            _name = name;
            _teachers = new List<Teacher>();
        }
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
        public List<Teacher> _teachers;
    }

 

public class Teacher
    {
        private string _name;
        public Teacher(string name)
        {
            _name = name;
        }
        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }
    }

 

public class ClientTester
    {
        public void AggregationTest()
        {
            var department = new Department("Electrical Engineering");

            var teacher1 = new Teacher("Teacher 1");
            var teacher2 = new Teacher("Teacher 2");

            department._teachers.Add(teacher1);
            department._teachers.Add(teacher2);

        }
    }

Karena object teacher di buat di luar object department, sehingga jika object department dihancurkan maka object teacher tetap exist. Object department bisa memiliki banyak object teacher yang berasosiasi dengannya, tapi tidak sebaliknya. Sehingga dalam relasi ini object department adalah owner dari object teacher.

Relasi Agregasi disebut juga Weak Assosiation dan dalam UML disimbolkan seperti ini

agregasi

 

Composition (Komposisi)

Komposisi sama dengan relasi Agregasi, tapi lebih spesfic lagi yaitu lifecycle object bergantung pada object ownernya.

public class University
    {
        private string _name;
        private List<Department> _departments;
        public University(string name)
        {
            _name = name;
        }

        public string Name
        {
            get { return _name; }
            set { _name = value; }
        }

        private void GenerateDepartment()
        {
            var electricalDepartment = new Department("Electrical Engineering");
            var biologyDepartment = new Department("Biology");
            _departments = new List<Department>
                {
                    electricalDepartment,
                    biologyDepartment
                };

        }
    }

 

public class ClientTester
{
  public void CompositionTest()
  {
      var university = new University("Diponegoro University");

   }

 }

Pada contoh ini class University bertindak sebagai object owner seperti pada relasi Agregasi di atas. Karena object electricalDepartment dan biologyDepartment di buat di dalam object univerty sehingga jika object university dihancurkan, maka object electricalDepartment dan biologyDepartment akan tidak exist lagi. Relasi Komposisi disebut juga Strong Association atau Death Relationship dan disimbolkan dalam UML seperti ini

komposisi

 

 

 

Sarung

Menurut catatan sejarah, sarung berasal dari Yaman. Di negeri itu sarung biasa disebut futah. Sarung juga dikenal dengan nama izaar, wazaar atau ma’awis.Masyarakat di negara Oman menyebut sarung dengan nama wizaar. Orang Arab Saudi mengenalnya dengan nama izaar.

Penggunaan sarung telah meluas, tak hanya di Semenanjung Arab, namun juga mencapai Asia Selatan, Asia Tenggara, Afrika, hingga Amerika dan Eropa. Sarung pertama kali masuk ke Indonesia pada abad ke 14, dibawa oleh para saudagar Arab dan Gujarat. Dalam perkembangan berikutnya, sarung di Indonesia identik dengan kebudayaan Islam.

Saya sangat suka menggunakan sarung, kain yang mampu menghangatkan dari udara dingin tapi tidak bikin gerah dikala panas.

Di kampung saya di Mandar sana kami punya banyak stok sarung untuk  bermacam keperluan. Sejak kami lahir kami sudah dibungkus pakai sarung, ayunan bayi pun menggunakan sarung. Mandi sebagai pengganti handuk, kami pakai menggunakan sarung walaupun jadinya lebih lama kering di banding handuk. Apalagi buat tidur, ampuh untuk melindungi dari nyamuk dan dinginnya malam.  Ke masjid tak afdhol kalau tidak pakai sarung. Ke acara yang formal seperti ke kondangan pun pakai sarung. Bahkan orang meninggal dialasi sarung sembari didoakan oleh orang yang datang melayat.

Interface, penting tapi sering diabaikan

Beberapa kali saya melakukan interview untuk kandidat programmer di kantor, seringkali untuk pertanyaan paling dasar mengenai Object Oriented Progamming adalah pertanyaan apa itu Interface? sebagian candidat biasanya menjawab pernah menggunakan tapi tidak bisa mengungkapkan dalam secara verbal. Bahkan ada yang menjawab bahwa itu adalah antarmuka (hmm, mungkin dikiranya User Interface).

Walaupun ada teman yang menganalogikan interface adalah template, tapi bagi saya analogi interface yang paling mendekati adalah bahwa interface itu semacam contract yang mengikat semua child class (semua class yang mengimplementasikan interface tersebut).

Di dalam sebuah interface bisa jadi berisi sekumpulan method dan property. Ingat, sebuah interface tidak bisa memiliki implementasi di dalamnya, berbeda dengan abstract class. Dengan menggunakan interface, memudahkan kita membuat mockup object dalam unit test misalnya. Terutama jika kita menggunakan IoC container. Interface ini adalah salah satu feature dalam OOP yang digunakan untuk prinsip polymorphisme.

Contoh:

interface IFlyObject
        {
            void Fly();
        }

Selanjutnya kita buat class Bird dan Plane yang akan mengimplementasi IFlyObject.

interface

Akan ada muncul compiler error jika interface member dari IFlyObject yaitu Fly() tidak di implementasikan. Mari kita modifikasi class di atas.

public class Bird : IFlyingObject
        {
            public void Fly()
            {
                Console.WriteLine("Terbang dengan Sayap Bulu");
            }
        }

        public class Plane : IFlyingObject
        {
            public void Fly()
            {
                Console.WriteLine("Terbang dengan mesin jet");
            }
        }

Salah satu prinsip OOP adalah Polymorphisme. Polymorphisme artinya kita memproses object-object yang berbeda berdasarkan tipe datanya. Dengan kata lain sebuah method yang memiliki implementasi berbeda-beda, implementasinya dapat dipilih saat runtime bergantung pada kondisi tertentu. Dari Polymorphisme kita mendapatkan keuntungan berupa flexsibilitas dalam memilih class implementasi.

static void Main(string[] args)
        {
            Console.Write("Pilih (A) Bird (B) Plane : ");
            var input = Console.ReadLine();
            IFlyingObject flyObject;
            if (input.ToUpper() == "A")
            {
                flyObject = new Bird();

            }
            else if (input.ToUpper() == "B")
            {
                flyObject = new Plane();

            }
            else
            {
                throw new Exception("Pilih A atau B");
            }
            flyObject.Fly();
            Console.ReadKey();
        }

Lebih jelas penggunaanya nanti kita akan bahas pada tulisan mengenai SOLID Pattern

Generic Repository Entity Framework Part II

lanjutan dari Generic Repository Entity Framework Part I

Unit Of Work

Unit Of Work memastikan bahwa banyak repository hanya akan menshare satu database contex yang sama sehingga membuat transaksi menjadi atomic. Artinya jika satu gagal, semuanya gagal untuk menjaga konsistensi data.

Seperti biasa, kita buat interfacenya dulu.

public interface IUnitOfWork : IDisposable
     {
         IGenericRepository GetGenericRepository()
           where T : class;

         void SaveChanges();
     }

Kemudian kita membuat konkrit classnya.

public class EFUnitOfWork : IUnitOfWork
     {
         private BookStoreEntities _context = new BookStoreEntities();
         private bool _disposed;



         /// <summary>
         /// Gets the generic repository.
         /// </summary>
         /// <typeparam name="T"></typeparam>
         /// <returns></returns>
         public IGenericRepository<T> GetGenericRepository<T>() where T : class
         {
             return new EFGenericRepository<T>(_context);
         }


         /// <summary>
         /// Saves the changes.
         /// </summary>
         public void SaveChanges()
         {
             try
             {
                 _context.SaveChanges();
             }
             catch (DbEntityValidationException e)
             {
                 throw;
             }
         }

         /// <summary>
         /// Releases unmanaged and - optionally - managed resources.
         /// the dispose method is called automatically by the injector depending on the lifestyle
         /// </summary>
         /// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
         protected virtual void Dispose(bool disposing)
         {
             if (!this._disposed)
             {
                 if (disposing)
                 {
                     _context.Dispose();
                 }
             }
             this._disposed = true;
         }

         public void Dispose()
         {
             Dispose(true);
             GC.SuppressFinalize(this);
         }
     }

 

Nantinya kita akan membuat instance dari Generic Repository di atas dengan melewatkan class entities sebagai paramater dan menggunakan method GetGenericRepository

public class BookBLL : IBookBLL
        {
            private readonly IUnitOfWork _unitOfWork;
            private readonly IGenericRepository _bookRepo;
            public BookBLL(IUnitOfWork unitOfWork)
            {
                _unitOfWork = unitOfWork;
                _bookRepo = _unitOfWork.GetGenericRepository();
            }