วันอาทิตย์ที่ 31 มีนาคม พ.ศ. 2556

Special Chapter : Programmer Behavior (My Behavior)

วันนี้ค่อยรู้สึกเหมือนการเขียน blog จริงๆ ซะที ก็พูดถึงตัวเองนี่เนอะ

วันนี้จะมาเล่าถึงพฤติกรรมของโปรแกรมเมอร์หรือตัวผมนั่นเอง เอาตัวเองเป็นกลุ่มตัวอย่าง เหมือนพวกโพลต่าง ๆ ไง

วันนี้จะมาเขียนแต่ในด้านที่ดีนะครับ เสนอแนะได้ คุยเล่นได้ กวนได้ ไม่ซีเรียสครับ ผมไม่คิดมาก

มาข้อแรก 1. การเขียนโปรแกรมต้องมองจุดมุ่งหมายเป็นสำคัญ

เวลาผมเขียนโปรแกรมหรืออ่าน spec ที่ทาง SA เขียนมาให้ หรือที่ลูกค้าให้ก็ตาม ผมก็จะพยายามอ่านจุดมุ่งหมายของคนที่ให้มาให้เคลียร์ หรือถ้าไม่เคลียร์ก็ต้องถามให้เคลียร์ คือถ้าเราเข้าใจจุดมุ่งหมายแล้ว เราก็จะสามารถเข้าใจความคิดว่าที่ทำเพื่ออะไร ซึ่งจะทำให้เราสามารถเสนอสิ่งที่ดีกว่า หรือแก้ไขให้มันดีขึ้นได้ ซึ่งเป็นสิ่งสำคัญที่จะได้ไม่ต้องทำงานหลายรอบ ปัญหาส่วนใหญ่ที่เราต้องแก้งานเรื่อย ๆ เนื่องจากไม่พยายามทำความเข้าใจจุดมุ่งหมาย แต่พยายามทำตาม spec ที่ให้มาโดยคิดว่าอยากได้ก็ทำให้โดยคิดว่าเราไม่ผิดเค้าให้มาผิดก็เป็นความผิดของเค้า ซึ่งสุดท้ายแล้ว เราก็ต้องแก้อยู่ดี เพราะฉะนั้นพยายามทำให้ดีที่สุด หากเข้าใจจุดมุ่งหมายที่ชัดเจนแล้ว จากงาน 100 เราจะทำได้ 120 – 200 เพราะว่าเราจะสามารถเขียนโปรแกรมเพื่อรองรับอนาคตที่จะเกิดขึ้นต่อจากนั้นได้อีก (เห็นด้วย กด 1,  ไม่เห็นด้วย กด 2)

2. ใช้ google และต้องทำความเข้าใจ google 
เอ่อ ตัวผมหรือหลาย ๆ คนก็ติด google ครับ เพราะมันบอกเราได้ทุกอย่าง เวลาเอาโค้ดชาวบ้านมา ตัวผมก็จะพยายามทำความเข้าใจว่า ทำไมเค้าถึงทำแบบนั้น ผมไมถึงได้ผลแบบนั้น ก็จะพยายาม comment บรรทัดโน้น แก้บรรทัดนี้ และดูผลลัพธ์ที่ออกมา เพราะส่วนใหญ่แล้วโค้ดที่ได้มา จะเอามาใช้ได้ซัก 70 ส่วน แต่หากเราพยายามทำความเข้าใจเราจะได้ความรู้เพิ่มมาอีกมากมายครับ เพราะการดูโค้ดคนอื่น ทำให้เราได้แนวคิดในการประยุกต์แบบใหม่ ๆ เกิดขึ้นมา โค้ดที่ผิด และที่ถูก ก็ให้ความรู้กับผมได้เสมอครับ ตัวอย่างความรู้ที่ได้ !important โอ้ตอนเห็นครั้งแรกมันใช้ทำอะไรน้อ พอเอามาใช้แล้วโอ้ อ้าว สุโค่ย ใครยังไม่รู้ก็ถาม google นะครับ เพราะคราวนี้ไม่ได้สอนอะไรครับ 555

3. ปัญหาคือพลังของโปรแกรมเมอร์
ผมเคยทำโปรแกรมที่ไม่ต้องคิดอะไรเลย แค่สร้างฟิลด์ เพื่อเป็น Object สำหรับสร้างรายงาน ซึ่งทำซ้ำๆ เยอะมากๆๆ ซึ่งยังเป็นอะไรที่น่าเบื่อมาก เรียบง่าย ไม่มีอะไรเลย ซึ่งแทบจะหลับตาพิมพ์เลยครับ 555 (ผมหลับตาพิมพ์ได้ถูกมากกว่าลืมตาครับ) แต่เวลาที่สนุกที่สุดคือเจอบั๊ค มีปัญหา ช่วยดูหน่อย คำพวกนี้เวลาผมได้ยินจะกระดี๊กระด๊ามาก 555 แบบว่ารอมาตั้งนานแล้ว และจะ switch ไปหาปัญหาทันที คนอื่นลุกลน แต่ผมเหมือนได้เจอของเล่น ตื่นทันทีทันใดเลย ไม่รู้ผมเป็นคนเดียวรึเปล่าน้อ มาแชร์กันได้ครับ

4. สิ่งที่ลำบากใจมากที่สุดและสำคัญที่สุดคือการตั้งชื่อ
ชื่อของสิ่งต่าง ๆ ไม่ว่าคลาส ตัวแปร ชื่อฟิลด์ ชื่อฟังก์ชั่น ผมว่าเป็นสิ่งที่สำคัญที่สุดเลยนะ เพราะหากทำไว้ดีการแก้ไขก็จะสามารถทำได้สบายมาก พยายามตั้งให้เป็นรูปแบบเดียวกัน เช่นอะไรที่ใช้ในการค้นหาผมก็จะลงท้ายด้วย Cond อะไรที่เป็นอาเรย์ก็จะตั้งเป็น Arr ส่วนเป็นการติดต่อกับ database ก็จะเป็น DAO (Data Access Object) นั่นเองครับ ซึ่งหากเห็นแค่คำลงท้ายเราก็จะมองเห็นค่าที่อยู่ด้านในทันที หรืออะไรที่เป็นชั้น ๆ ก็จะเป็น Main, Sub1, Sub2 ไปเรื่อย ๆ หรือแม้กระทั่งส่วนที่เป็นชื่อจริง ๆ ก็ตั้งให้สื่อกับตัวมัน คำไหนที่เห็นแล้วก็ต้องอ๋อตัวนั้นนั่นเอง 555

5. อะไรที่ต้องทำซ้ำ ๆ กันหรือใช้ชื่อแบบเดียวกัน ให้ทำเป็น Class ซะ
อันนี้เป็นแนวคิดที่ว่าในหน้าต่างๆ บางหน้าหรือหลายหน้าอาจจะมีการทำงานที่คล้าย ๆ กัน เหรือแตกต่างกันบางส่วน เช่นการดึงข้อมูล การนำข้อมูลในใส่ในหน้าเวป ซึ่งการทำงานมันจะคล้ายๆ กันแต่ข้อมูลที่ดึงมาได้จะไม่เหมือนกัน อยากใช้ชื่อเดียวกัน ทำไงดี ซึ่งผมก็แยกออกเป็นคนละคลาสทันที โดยมีเมธอดชื่อเดียวกัน copy ไปและเปลี่ยนชื่อ class และการทำงานนิด ๆ หน่อย ๆ ก็เรียบร้อยครับ หากเป็น javascript ก็ทำการ new Object(); มาใช้ทันทีครับ


คราวนี้ 5 ข้อก่อนนะครับ เหนื่อยและ เห็นด้วยไม่เห็นด้วยหรืออยากจะเถียงหรือเพิ่มเติมข้อไหนก็บอกมาได้ครับ เผื่อจะได้แนวคิดใหม่ ๆ

วันอังคารที่ 26 มีนาคม พ.ศ. 2556

JAVEEE : Servlet Part 6 Servlet Responsibility

Servlet วันนี้มาคุยกันแบบชิวๆ ครับ ใครว่า Servlet ของเราควรจะอยู่ตรงไหนของโปรแกรมกันแน่ครับ

Servlet คุณลักษณะหลักๆ จะเป็น java class ที่ไม่ได้มี html tag ใดๆ ทั้งสิ้น เพราะฉะนั้น ..... ปิ๊งป่องใช่แล้วครับ ใช้ในการทำงานหรือเรียกว่า controller ใน model ของ MVC นั่นเอง ด้วยเหตุที่ว่า servlet ไม่ได้ถูกเจาะจงให้แสดงผลเป็น html แต่เจาะจงให้เป็นอะไรก็ได้ที่ทำงานอยู่เบื้องหลัง เช่นการติดต่อ database การบันทึก log ของระบบ นั่นก็คืออะไรที่ไม่แสดงออกทางเว็บก็โยนให้ Servlet ทำให้หมดครับ

  - ติดต่อ Database เพื่อทำการดึงข้อมูล
  - เก็บ log ของคนใช้งาน
  - download File
  - export รายงานต่าง ๆ

ข้อ 2 Servlet เป็น Server Side Script ใครอธิบายได้บ้าง...........   เอ่อ อ่าาา อ่าฮะ  โอเคหมดเวลา ทุกคนตอบถูกครับ ความหมายของมันคือ Server Side Script ก็คือ Script ที่รันอยู่ฝั่ง Server นั่นเอง ซึ่งหากเราอ้าง File file = new File("d:/test"); นั้นก็คือ drive "d:/test" ที่อยู่บนเครื่อง Server ที่ Application ของเรารันอยู่นั่นเองครับ ซึ่งสิ่งที่ต้องตระหนักก็คือ คนที่เข้าึถึง resource ของฝั่ง server คือ Web Application ครับ สิทธิจึงเท่ากับ User ที่เป็นเจ้าของ service นั่นเอง


เอาหละ ผมนึกออกแค่นี้ ใครข้องใจตรงไหนอีกก็ฝากคำถาม หรือเสนอแนะมาได้ครับ รับฟังทุกคนครับ

JAVAEE : Servlet Part 5 Scope

วันนี้เรามาลุยเรื่อง Scope กันเต็มตัวครับ เปรยมาสองตอนด้วยกัน

Scope เป็นศัพท์ที่ใช้เรียกขอบเขตของตัวแปรว่าค่าจะมีชีวิตอยู่ถึงตอนไหนกันแน่ครับ ซึ่งมีด้วยกัน 4 Scope

1. Page Scope
   page Scope เป็น Scope ที่เล็กที่สุดครับ ซึ่งค่าของตัวแปรที่อยู่ใน Scope นี้จะมีค่าอยู่แค่ในหน้าปัจจุบันเท่านั้นครับ
  การใช้งาน ผมเคยเห็นแต่ใน jsp ครับ
   - pageContext.setAttribute("name");
   - pageContext.getAttribute("name");

2. Request Scope
    request Scope เป็น Scope ที่ค่าจะอยู่จนกระทั้ง Request Life Cycle จบลง ใครจำไม่ได้ย้อนอ่านบทก่อนหน้าครับ ใช้บ่อยสุด หากทำตามรูปแบบ MVC ครับ
  - request.setAttrubute("name");
  - request.getAttribute("name");

3. Session Scope
    session Scope เป็น Scope ที่ใช้เก็บข้อมูลของผู้ใช้ เพราะจะอยู่จนกระทั่งปิด browser หรือเราลบออกไปครั
// In Servlet
   - request.getSession().setAttribute("name");
   - request.getSession().getAttribute("name");
   - request.getSession().removeAttribute("name");

// In Jsp
   - session.setAttribute("name");
   - session.getAttribute("name");
   - session.removeAttribute("name");

4. Application Scope
    application Scope ใหญ่มากๆ เพราะเป็นตัวแปรที่อยู่ในระดับของ application ซึ่งไม่เฉพาะของเราคนเดียว ใครก็ตามที่เข้ามาใน application เดียวกัน ก็จะเห็นค่าเดียวกันครับ ลองดูตัวนี้เจ๋งมาก ถึงจะไม่ค่อยได้ใช้ก็เถอะ

// In Servlet
  - request.getServletContext().setAttribute("name");
  - request.getServletContext().getAttribute("name");
  - request.getServletContext().removeAttribute("name");

// In Jsp
  - application.setAttribute("name");
  - application.getAttribute("name");
  - application.removeAttribute("name");

ฝึกใช้กันเยอะๆ นะครับ เพราะเด๋วจะเจออีกเยอะครับ

วันจันทร์ที่ 25 มีนาคม พ.ศ. 2556

JAVAEE : Servlet Part 4 Request Life Cycle

วันนี้มาเรียนรู้ Request Life Cycle หรือวิถีชีวิตของ Request นั่นเอง

Request ของ Servlet มีชีวิตและตายได้นะครับ ซึ่งนั้นก็คือ Request Scope ที่จะได้เรียนถัดไปนั่นเอง

เมื่อมีการเรียกเข้ามา 1 ครั้ง ก็จะเกิดการสร้าง thread เพื่อมารับ request และประมวลผลและส่งกลับ นั้นคือ 1 request ซึ่งจริงๆ ดูง่ายๆ ครับ หาก url ยังไม่เปลี่ยนไปนั่นแสดงว่า request เดิมครับ

มี 2 เมธอดมาแนะนำ

// MyServlet

RequestDispatcher rd = request.getRequestDispatcher("page2.jsp");
rd.forward(request,response);


กับ
response.sendRedirect("page2.jsp");

หาก เรียกมาที่ MyServlet?param1=test


  แบบ 1  url ที่จะได้จะเป็น MyServlet?param1=test  อยู่ ที่หน้า page2.jsp หากแสดงค่า request.getParameter("param1"); ก็จะได้ค่า test ที่เราส่งให้ไปครับ สังเกตว่าแม้อยู่ในหน้า page2.jsp ก็สามารถรับค่า parameter ที่ส่งมาจาก MyServlet ได้อยู่แสดงว่าเป็น Request เดียวกันอยู่ครับ


แบบ 2 url ที่จะได้จะเป็น page2.jsp ซึ่งเมื่อทำแบบเดียวค่า request.getParameter("param1"); ก็จะได้ค่าเป็น null ซึ่งเป็นค่าว่างเปล่าของ String ใน java นั่นเอง


สำหรับ jsp  ก็คือจะมี jsp:forward ใช้สำหรับเพื่อให้เป็น request เดียวกันครับ และ jsp:forward ได้ครับ ซึ่งจะเป็นการเปลี่ยนไปหน้าถัดไปโดยไม่สนใจค่าในหน้าเดิมเลยครับ

JAVAEE : Servlet Part 3 Request and Response

ครับวันนี้เรามาทำความเข้าใจเรื่องของ HttpServletRequest กับ HttpServletResponse ครับ

HttpServletRequest กับ HttpServletResponse เป็น 2 ค่าที่ส่งมาเข้า method service ของเราครับ

HttpServletRequest
   HttpServletRequest ใช้ในการจัดการกับค่าทั้งหมดที่ request มาจาก client ครับ ได้แก่อะไรบ้างเอ่ย
    1. parameter ต่างๆ ใช้ request.getParameter
    2. คนส่งมาเป็นใครกันแน่ ใช้ request.getRemoteAddr(), request.getRemoteHost(), request.getRemotePort(), request.getRemoteUser()
    3. ส่งมาเป็น method อะไรน้อ request.getMethod จะได้เป็น GET , POST, PUT, DELETE
    4. ข้อมูล Header ของ package ใช้ request.getHeader(String headerName); เช่นค่าของ user-agent ครับ

ท่องไว้ว่าอยากได้อะไรจาก client ใช้ request ครับ

HttpServletResponse
  HttpServletResponse ใช้ในการส่งค่าจาก Server ไปยัง Client ครับ มีอะไรบ้าง
      1. ส่ง html กลับไปยัง client แน่นอนอ่ะ (response.getWriter)
      2. ใส่ cookie ไปยัง client (response.addCookies())
      3. การกำหนด header เพื่อกำหนดคุณลักษณะของค่าที่จะส่งกลับ response.setContentType("text/html")
      4. การ forward ไปหน้าใหม่ (response.sendRedirect(String page))

ปล. แค่มี 2 ตัวนี้เราก็เล่นอะไรได้อีกเยอะแล้วครับ

JAVAEE : Servlet Part 2 Servlet History

Servlet เราจะมี 2 ยุคด้วยกัน คือ
Servlet 2.5 ซึ่งใช้กับ JAVAEE 5
และ Servlet 3.0 ซึ่งใช้กับ JAVAEE 6 ขึ้นไปครับ
จะเจาะเฉพาะ Servlet 3.0 นะครับ อันเก่ามันเก่าไปและ 555

มาท้าวความกันครับ
Servlet ดั้งเดิม

package com.test;

import java.servlet.http.HttpServlet;
import java.servlet.http.HttpServletRequest;
import java.servlet.http.HttpServletResponse;

public class MyServlet exends HttpServlet {
  
     protected void doGet(HttpServletRequest request, HttpServletResponse response){
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            PrintWriter out = response.getWriter();

            out.println("Hello World Get");
     }


    protected void doPost(HttpServletRequest request, HttpServletResponse response){
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            PrintWriter out = response.getWriter();
            out.println("Hello World Post");
     }
}
อ่าฮะ Java Class สืบทอดมาจาก HttpServlet แค่นี้ตัวนี้ก็เป็น Servlet เรียบร้อยแล้ว และทำการ override method doGet เพื่อจะรับผ่าน GET request ครับ ซึ่งคือการเรียกผ่านทาง url เช่นเดียวกับที่ google ใช้ในการ search ครับ ซึ่งหากเรียกมาก็จะแสดงค่า Hello World Get ครับ

อีก override method doPost ก็คือการรับค่าผ่าน POST request ครับ นั่นก็คือส่งผ่าน body ของ package ซึ่งจะมองไม่เห็นใน url จะทำให้ส่งค่าได้มากขึ้นและปลอดภัยเนื่องจากไม่แสดงทาง browser ด้วยครับ

โครงสร้าง Project
MyProject
 - src
      - com.test.MyServlet
 - WebContent
      - WEB-INF
          - web.xml

ซึ่ง web.xml เป็น config เพื่อใช้ในการปรับแต่งลักษณะต่างๆ ของ Web Application ของเราครับ วันนี้เสนอการ mapping Servlet ด้วย
   <servlet>
    <servlet-name>MyServlet</servlet-name>
    <servlet-class>com.test.MyServlet</servlet-class>
  </servlet>

  <servlet-mapping>
    <servlet-name>MyServlet</servlet-name>
    <url-pattern>/MyServlet</url-pattern>
  </servlet-mapping>

ในแบบดั้งเดิมเราจะทำการ mapping servlet ใน web.xml ซึ่งมี 2 tag หลักๆ คือ

 <servlet> ซึ่งเป็นตัวบอกว่าจะใช้ชื่ออะไรในการอ้างถึง Servlet class ของเรา และ

 <servlet-mapping> เป็นตัว mapping ระหว่าง Servlet name กับ url ซึ่งเป็นตัวบอกว่า Servlet ของเราจะต้องเข้าถึงด้วย url อะไรครับ ใครอยากได้ .html ก็สามารถใส่เป็น /MyServlet.html ได้นะครับ

 ------------------------------------------------
Servlet 3.0
ในเวอร์ชั่นนี้ web.xml เป็นแค่ส่วนเสริมครับ ซึ่งจำทำแบบเดิมก็ได้หรือใช้ annotation @WebServlet ก็ได้ครับ


package com.test;

import java.servlet.http.HttpServlet;
import java.servlet.http.HttpServletRequest;
import java.servlet.http.HttpServletResponse;

@WebServlet("MyServlet")
public class MyServlet exends HttpServlet {
  
     protected void doGet(HttpServletRequest request, HttpServletResponse response){
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            PrintWriter out = response.getWriter();
            out.println("Hello World Get");
     }

    protected void doPost(HttpServletRequest request, HttpServletResponse response){
            request.setCharacterEncoding("utf-8");
            response.setCharacterEncoding("utf-8");
            PrintWriter out = response.getWriter();
            out.println("Hello World Post");
     }
}

JAVAEE : Servlet Part 1 What is Servlet?

เปิดตัวพระเอกครับ คุณจะได้รู้ว่าเค้าเป็นใครกันแน่

โครงสร้างพื้นฐาน
Servlet คือ Java Class ที่สืบทอดมาจาก HttpServlet ครับ

ซึ่ง HttpServlet นั้นมี method ทีเป็นพระเอกหลักๆ ได้แก่

   init()  อันนี้เป็นเมธอดที่ถูกเรียกต้อง servlet ถูกสร้างขึ้นมาครับ โดยเรียกครั้งเดียวเท่านั้นต่อ Web Container

   service(HttpServletRequest request, HttpServletResponse response) เป็นเมธอดที่ถูกเรียกทุกครั้งที่มี Request เข้ามาครับ ซึ่งมันจะทำหน้าที่ดูว่า request นั้นเป็นประเภทไหน และทำการส่งต่อไปยัง method ที่รับหน้าที่นั้นๆ ต่อไปครับ ที่ดังๆ ก็คือ GET,POST ซึ่งจะถูกส่งเข้า doGet และ doPost ตามลำดับครับ

   destroy() เป็นเมธอดที่ถูกเรียกตอนที่ Servlet ตายครับซึ่งจะเป็นตอนที่ Web Container ถูกปิดตัวลงนั่นเอง ส่วนใหญ่ใช้เพื่อเก็บ state ของ servlet ไว้ เวลาเปิดใหม่จะได้สามารถดึงค่าเก่ามาไว้ได้เหมือนเดิมครับ

พฤติกรรมของ Servlet (Servlet Behavior)
    Servlet นั้นจะถูกสร้างเพียงครั้งเดียวเท่านั้น และจะมีเพียง Object เดียวต่อ Container เท่านั้น ซึ่งเวลามี request เข้ามาจะเกิดการสร้าง thread เพื่อใช้สำหรับติดต่อกับ instance ของ Servlet ซึ่งมีเพียงตัวเดียวเท่านั้น ซึ่งช่วยในการลดการใช้ memory
    นั่นแสดงว่า หากคุณสร้างตัวแปรไว้เป็นระดับ instance ของ class แล้ว เมื่อมีการติดต่อหรือเปลี่ยนแปลงค่า ทุกคนที่เข้ามาก็จะเป็นการเข้าถึงตัวแปรเดียวกัน ซึ่งทุกคนก็จะเห็นค่าเดียวกันซึ่งเป็นค่าล่าสุดครับ

Life Cycle
เริ่มจาก init() ครับ คราวนี้ Servlet เราก็เกิดเรียบร้อย

ต่อมาเมื่อมี request เข้ามาก็จะทำการเรียก doService และ forward ไปยัง doGet และ doPost เพื่อประมวลผลและตอบกลับ ซึ่งจะเป็นอย่างนี้ไปเรื่อยๆ จนกว่าจะปิด Web Container

สุดท้าย destroy() เกิดตอน Servlet ตายครับ ลอง System.out.println("destroy") แล้วลอง start tomcat และเล่นๆๆๆๆ จนปิด tomcat ดูครับ คุณจะเห็น destroy ตอนปิด tomcat นั้นเอง

สรุปวันนี้
1. ใครอยากเป็น Servlet ก็ extends HttpServlet ซะ
2. ค่าไหนอยากกำหนดเริ่มต้นก็ใส่ใน init() โล้ด
3. ค่าไหนที่ไม่อยากแชร์ให้ชาวบ้านรู้ก็อย่าประกาศเป็น instance ของคลาสนะครับ