การออกแบบฐานข้อมูลแบบไหนดีกว่ากัน ระหว่าง Column เยอะ กับ join เยอะ

วันนี้พอดีไปอ่านเจอความเห็นใน narisa เลยเอามาแปะไว้สักหน่อยครับ

Question :

การออกแบบฐานข้อมูลแบบไหนดีกว่ากัน ระหว่างคอลัมน์เยอะ กับ join เยอะ

minimalist say :

หากเป็นตารางที่ใช้เพื่อ query ไปออกรายงาน แสดงว่า data operation (consumption) behavior คือ read
และกรณีที่ business logic ในการดึงข้อมูลและประกอบข้อมูลเพื่อออกรายงานไม่ซับซ้อนนัก

โซลูชั่น:
ออกแบบเป็นตารางเดียวไปเลยก็ได้
กำหนดกฏเกณฑ์ให้ตารางนี้มีแค่ read กับ insert พอ ไม่ควรให้ update และ delete ได้ ยกเว้น record มันเริ่มเยอะ และมี record ที่ไม่ได้ใช้หรือ obsolete ต่อการ read ไปออกรายงานเยอะ ก็ทำงาน backup เอาไว้ ทำได้หลายวิธี เช่น read แล้วเอาไปเก็บในตาราง backup หรือลง backup storage แต่ควรทำนานๆ ครั้ง พอ backup เสร็จค่อย delete ในตารางเดิม จะทำให้ตารางนี้ไม่มีการ update เด็ดขาด หากอยากอัพเดต ให้ delete ของเก่าแล้ว insert ใหม่ เพื่อคุม operation ให้มีแค่ read, insert, delete (นานๆ ครั้ง) ก็จะช่วยเรื่อง performance index ไม่ให้ drop นักได้
แยกตารางนี้ออกมาจากตารางที่ทำ transaction คือเป็นตารางที่เก็บ trasaction data ที่มีทั้ง insert, update, delete เพราะตารางแบบนี้มี movement สูง เป็นการ write มากกว่า read เราก็แยกตารางเพื่อ read กับ write ไปเลย จะเอาข้อมูลทรานแซกชั่นมาเก็บแบบ real time ก็ลงตารางทรานแซกชั่น ข้อมูลที่จะเอาไปออกรายงานก็เอาไปลงอีกตาราง ทำให้ช่วยลด concurrently access ได้
2 ตารางข้างต้นจะแยกไปเก็บยังดิสก์คนละตัวกันก็ได้ จะได้แยก I/O ได้อีก ช่วย performance ได้
query อย่าซับซ้อนเกินไป ดึงเป็นข้อมูลดิบแล้วเอาไปตบแต่งรูปแบบผลลัพธ์ต่อที่ระดับเซอร์วิสหรือแอพพลิเคชั่นก็ได้ เพื่อลดโอเวอร์เฮดของ database
สร้าง index ให้สัมพันธ์กับหน้าจอป้อนเงื่อนไขออกรายงาน อย่าให้ซับซ้อนนัก

ทริกนะครับ: แยกให้ออกระหว่าง ข้อมูล กับ data presentation ถ้าเอา 2 เรื่องนี้โยนไปให้ database ทำ ก็จะซับซ้อนและเปลือง performance ได้

Continue reading

Mocks and Stubs

Test Double  เป็นวิธีการที่่ช่วยให้เราสามารถเขียน Test ได้ง่ายและเร็วขึ้น เนื่องจากปกติแล้ว Class ที่เราต้องการ Test (System Under Test : SUT) มักจะ Dependency กับ Class หรือ External System อื่น เช่น Repository class, Database,  Email  หรืออะไรก็ตาม ดังนั้นทางแก้คือ เราก็จะใช้ Test Double มา Replace Object เหล่านี้ เพื่อให้เราควบคุมผลลัพธ์ระหว่างการ Test ได้ตามที่ต้องการ โดย Test Double แบ่งออกได้ดังนี้ Dummy, Fake, Stubs, Spies, Mocks

วันนี้ผมจะขอกล่าวเฉพาะ Mocks กับ Stubs ซึ่งทั้ง 2 ตัวนี้เป็นอะไรที่หลายๆคน สับสน และเรียกสลับกันบ่อยๆ (รวมทั้งตัวผมด้วย)  เอาเป็นว่าลองมาดูตัวอย่างกันครับ ผมกำหนด Class ที่ต้องการจะ Test (SUT) คือ CreateCustomerCommandHandler

public class CreateCustomerCommandHandler : ICommandHandler<CreateMemberCommand>
{
    private readonly ICustomerRepository _customerRepository;
    private readonly IUnitOfWork _unitOfWork;

    public CreateCustomerCommandHandler(
              ICustomerRepository customerRepository
            , IUnitOfWork unitOfWork)
    {
        _customerRepository = customerRepository;
        _unitOfWork = unitOfWork;
    }

    public void Execute(CreateMemberCommand command)
    {
        var emailExists = _customerRepository.EmailExists(command.Email);
        if (emailExists)
            throw new EmailAlreadyExistsException();

        var customer = new Customer(firstName: command.FisrtName
                            , lastName: command.LastName
                            , gender: (Gender)command.GenderID
                            , email: command.Email);

        _customerRepository.Add(customer);
        _unitOfWork.Commit();
    }
}

Continue reading

Domain Events III

บทความนี้เป็นภาคที่ต่อ ของ DomainEvents I และ DomainEvents II นะครับ
ผมขอสรุปคำจำกัดความสำหรับ DomainEvent แบบนี้ครับ

DomainEvents คือ เหตุการณ์ (Events)ที่เกิด “หลัง” จากที่ Domain Object ทำการ Action Behavior (Call Method) ใดๆนั่นเอง

ยกตัวอย่างเช่น หลังจากที่ Order ถูก Submit เรียบร้อยแล้ว ให้ทำรายการต่อไปนี้
1. ส่ง Email ไปยัง Customer
2. ส่ง Email ไปยัง Admin

แล้วแต่ว่า Business ของระบบนั้นๆจะเป็นยังไง

ในมุมมองของการ Implement สำหรับ .Net เรามี events หรือ delegate สำหรับทำ Events อยู่แล้ว ทำไมเรายังต้องมี Domain Events ด้วย ลองมาดูกันครับ สำหรับกรณีที่เรา Implement แบบปกติ Continue reading

Arts-Science and Software Architecture

Architecture is About Intent, not Frameworks

ผมเชื่อว่าหลายๆ คนคงจะคุ้นเคยกับการแบ่ง Software Layer ของเราเป็นอย่างดี เช่น 2-Layer,3-Layer,N-Layer, DDD Layer,The Onion Architecture และแน่นอนว่า จุดประสงค์ของการแบ่ง Layer จะมุ่งเน้นเพื่อการแยกหน้าที่ของ Code ทำให้เราสามารถปรับเปลี่ยน หรือแก้ไข Code ได้ง่ายขึ้น ซึ่งทั้งหมดล้วนแล้วแต่เป็นการแบ่ง Layer ในเชิงของ Technical แทบทั้งสิ้น….ซึ่งก็ทำงานได้ดี และไม่ได้ผิดอะไร

3-layers

Continue reading

Avoiding Booleans

สิ่งหนึ่งที่ผมว่าเป็น Bad Design ก็คือ การใช้ Boolean ใน Method หรือ Function ต่างๆ เรียกอีกอย่างว่า Flag Argument ลองดูตัวอย่างนี้

     public interface ICustomerFactory
     {
         Customer CreateCustomer(string name, string address, bool isGoldCustomer);
     }

     public class CustomerFactory : ICustomerFactory
     {
         public  Customer CreateCustomer(string name, string address, bool isGoldCustomer)
         {
              if(isGoldCustomer)
              {
                   if(string.IsNullOrEmpty(address))
                      throw new BusinessRuleException("Invalid address");

                   // Logic for Create Gold Customer
              }
              else
              {
                   // Logic for Create Customer
              }
         }
     }

Continue reading

[GoF] – Proxy Pattern

ถ้าหากจะพูดถึงเรื่อง Design Pattern  เราก็คงคิดถึง Gang of Four (GoF) ซึ่งถือว่าเป็น Classic Pattern โดยประกอบไปด้วย 23 Patterns แยกเป็น 3 หมวด คือ Creational Patterns, Structural Patterns, Behavioral Patterns วันนี้ผมขอหยิบบาง Pattern ในหมวด Structural Patterns มาพูด ซึ่งมันก็คือ Proxy Pattern มาดูกันครับ..

Proxy Pattern : Provide a surrogate or placeholder for another object to control access to it.

gof-proxy

Continue reading