Thursday, August 30, 2007

The reverse angle of "Siebel and spring.net" and the steps of using Siebel

The reverse angle of "Siebel and spring.net" and the steps of using Siebel


When I say "Siebel and spring.net", I mostly mean to use spring.net to mimic Siebel. Here, Siebel is the "big brother", the "role model".

However, it is not that simple. I do not want to lose my C# or Java or VB skills.

In a sense, it is similar as I keep refreshing my C/C++ skills, periodically.

However, it is also very different, quantitative difference: C#, java, VB are still extremely useful for application development, while C/C++ are less useful for direct applications nowadays; however, they are useful, for understanding OS, and systems like Siebel (you may say an application level OS).

Without spring level of C# or java understanding, or directly C/C++ level -- they call it engineering level -- of understanding of Siebel itself, you will never really understand Siebel.

This is not just a theoretical bias: Siebel will be merged with/into Fusion -- without knowing Fusion or spring.net-like frameworks, you simply cannot understand new versions of Siebel easily and quickly.

Conclusion: you need to know spring.net (or spring itself, and OR mapping, and Ajax), in order to understand Siebel quickly and thoroughly.

It is important to note that plain C#/Java/VB simply does not cut it. You must know frameworks, OR mappings, AOP, databinding, Ajax. etc.

Hence, "Siebel and Spring.net", two sides, both are crucial.

A conclusion for practice: to use Siebel, there are three steps:
(i) immediately set up a usable system, using out-of-box features;

(ii) while (power) users are experimenting the system, you must do some second round of "requirement discovery and design". Because you need to find the features within Siebel, so, when use Siebel, at this stage, the key is NOT talking to users, it is letting users to experiment with Siebel, and you experiment it also, and read all documents, and and try to create a small (a few screens) but "deep" configured module. "Deep" does not mean heavy scripting, it means it includes all key powerful features (including scripting, but again, it does not need to be scripting heavy; but it should include using export to copy/paste some work!) . Again, the key is to get a small but "deeply configured" model done, while users are experimenting.

(iii) users are asking for some features that can be easily done; users also ask for some features that need "deep configuration". Negotiate a little (because Siebel must have a reason not doing that way! Perhaps the business process that Siebel suggests is a better way!). Then, prioritize, and use the deeply configured one as an example, implement more modules.

Obviously, step (ii) is crucial; and to do it right and quick, you need to know spring.net ;-)

Siebel (offline) client and need a toad-like tool for sybase anywhere

Siebel (offline) client -- talking about offline -- Siebel has been doing for a long time! Sometimes it is called thick client, or simply, client, confusing.


The offline client is also used for development environment. It uses sybase. Its build tool is like sqlplus -- we need a toad-like tool for sybase anywhere. Perhaps oledb connection can be fine, even use access -- I do not like access though; too much clicking, awkward.

BO-scoped workflow/EAI (and service), and BO-scoped rule engine

BO-scoped workflow/EAI (and service), and BO-scoped rule engine

A. BO scoped workflow, service, and EAI.

(i) workflow/task: you can always call workflow as a service -- workflow is executed within a service (the workflow engine). In other words, service is the underlining mechanism. If a scope is not enough, then, you can create another subworkflow.

(ii) service: you need service, because service can handle transaction, workflows cannot. BO can have a default scope of transaction. Just a note here, the Siebel server has some internal component. If you need to use it directly from client, then, you need to use "server request broker" -- a service interface.

(iii) EAI: service needs scripting, and we prefer declarative programming (to avoid clicking, we must learn to hack sif/xml exports), so, we want to avoid service per se. Also, service cannot use objects as parameters. So, we use EAI that can handle both transactions and object parameters.

B. BO-scoped rule engine

I used rule engine before, in a large project in java. We experimented it in many ways, and finally we concluded that it is not as powerful as it sounds. Inferences are not really that useful, for two reasons: (i) machine performance: we cannot load all the rules and (more importantly) and all those objects needed for those those rules in memory! (ii) human accountability: when something is not right, we cannot say that it is AI -- we are accountable! Basically this means we do not want it to be that powerful! We want predictability! -- As a result, perhaps M$'s no-inference rule engine approach is correct! Wait a minute, perhaps M$ only sees the part of it -- the real thing about rule engine is that it eliminates the effect of the order of rules. This is very important, because by a strong inference engine, we do not need to worry about the order anymore; in other words, this means (i) we need to be careful to specify the rules in such a way that they are order-independent. (ii) the string inference engine can help us to do that.

Anyway, because of the concept of "scope", rules engine is just a glorified "(intra and inter-) entity validation/logic" mechanism -- yes, this is the reason that I have not blog rule engine per se that much -- it is already covered by entity validation/logic (note: rules can change values also, so, it is not just "validation" per se). Rules are grouped special kind of fine-grained AOP.

In Siebel, BO scoped can help the system to help us also, by providing smaller number of options. Note that currently, Siebel cannot provide help for lookup values. It should; I guess, it will be in next version.

C. Why BO is so important? As indicated in my previous blogs, BO is UnitOfWork. For web or SOA, it is the request (or conversation, if we relax it a little bit). It ties OR mapping, facade, valiation/entity logic, and UI-view all together. If you really push it, asking what exactly is it? I would answer it is OR mapping with a context of AOP (coarse-grained facade and fine-grained entity).

Siebel Scripting: third party tool and future of scripting

Siebel Scripting

http://www.toolsandmethods.com/wordpress/?p=3
http://www.toolsandmethods.com/wordpress/?p=9

I will try the tool, as a learning tool. I am not sure I will ask the company to buy it, though.

To balance it, I want to say that when Oracle tries to merge Siebel into its Fusion architecture, it could "upgrade" eScript to java. I am not saying it will, but a possibility.

However, it is unlikely, because this will make M$ upset. Technically, java is better than eScript (even you add type and do some compiling -- treating it as if it were java -- another way to "handle" or "deal with" javascript -- remember google did it by compiling Java into javascript.). However, M$ shop is a big market.

Wednesday, August 29, 2007

More about Siebel BO, unit of work, service, workflow/task, escript and hacking sif/xml export

More about Siebel BO/unitOfWork, service, workflow/task, less escript by editing sif/xml export


1. Siebel BO and Hibernate unit of work

They are equivalent.

Note: A unitOfWork usually lasts longer (or, a lot of times the same) than a web-request but shorter than a web-session. This is what's called the session-per-"conversation" (for shopping carts or wizards) pattern by the hibernate-guys. If you use session-per-request, then, it is the idea of "view-BO" pair in Siebel -- told you!


2. A way to do minimum scripting

Workflow is good for making business rules explicit for power users. So, even it is now clumsy (not easy to test, drag and drop is much slower than typing in IDE etc), it is good that we keep using it.

So, we only need some "util" services from scripting -- at this level, it should be pure javascript. Not data.

All the logic outside validation and rules should be in workflow units that has low-level workflow logic. Usually this is necessary, because we need transactions (see below).

If we need explicit transaction, then, we use scripting to organize workflow units into a service.

Then, we use a workflow (or a task) to wire those workflow units, connect it to a big button or a web service.

3. I agree with the philosophy of less eScript, declarative programming is good. However, declarative does not mean "clicking": I believe Siebel is evil in this regard. There is a loophole here, I am going to hack it -- we can edit the sif/xml export files!

Tuesday, August 28, 2007

A minor but crucial correction about BO in Siebel

A minor but crucial correction about BO in Siebel

A BO by itself is still an entity, just a composite entity.
I mis-identified it with a facade, because it is almost the return value of a facade.

Another reason is that in "configuration", Siebel does not expose "facades"; yet, we still need a concept for facade, and BO is the closest thing we can get.

However, in workflow, scripting (eScript, i.e., javascript), and integration, the real 'facades" are exposed, they are, well, "business services", or "service mode workflows" -- all those are so "obvious", of course.

Again, my new "default architecture" is Siebel plus (i.e. in the "integration") Spring.net (or Spring itself, we do not care whether it is C# or java -- esp. when you use spring) that leads to OR mapping and Ajax that "mimic" Siebel.

Note that Siebel is not just a CRM software. It is a platform -- a small one, but nevertheless a general-purpose one -- it can be everything and anything. To me, it is a system for centralized security and logging, and it is an OR mapping system, validation system, and UI framework with excellent databinding and Ajax-like feature (mostly via ActiveX -- hey, nobody is perfect). The only downside is that it is expensive, and proprietary; to "correct" the problem, we have spring (+ OR + pure Ajax).

Monday, August 27, 2007

My new "default architecture": Siebel and Spring.net (and spring.net will lead to OR mapping and Ajax, via custom classes)

Finally, I find my new "default architecture": Siebel and Spring.net (and spring.net will lead to lower layer -- OR mapping and higher layer -- Ajax, via custom entity classes)


Siebel is already done, and it is beautifully done -- nobody can argue against that!

Spring.net has everything or at least can lead us to find everything that Siebel has.
-- spring.net itself is in the "middle"; however, it will lead to OR mapping (i.e. end of stored procedures) and pure ajax (i.e. end of server side ajax).

------------------details:

"Weak" but clear technical reasons (those reasons are implied in Java culture) that spring.net leads to OR mapping and Ajax.

(a) AOP leads to fine-tuned validation logic that needs custom classes; AOP also leads to non-code generation approach. Both lead to OR mapping. Note that if there are too much resistance on OR mapping, then, we can use code generation as an intermediate step. The key down side of OR mapping is that OR mapping software is too big to be maintainable, even you have all its source code.

(b) Fine-tuned validation logic also encourages high-interactive client. Windows is not an option. Silverlight is still one or two years away; so, pure ajax is the way to go. Note that the argument is that ajax not just makes user happy; pure ajax also makes development cleaner.

A recent note/modification: siverlight is the key here -- on the one hand, it will set the new standard here and therefore push ajax forward; on the other hand, it will compete with ajax, and win. So, it is possible that we will never use heavy javascript -- we use a dozen of new ajax third party controls, then, we switch to silverlight. So, the key of ajax is "new third party controls" (because we cannot wait for M$ for this!) -- client side or server side does not really matter; as long as it is "new", because new server side controls will always have client side API anyway (but we must discipline ourselves to use javascript minimum, because silverlight is already on the horizon, no need to use heavy javascript).

In short, strong "custom class" approach needs AOP; strong "custom class" approach will lead both OR mapping and ajax (or/and silverlight). As a result, AOP will lead OR mapping and pure ajax. Spring.net is AOP, so, spring.net will lead to OR mapping and pure ajax.

---------------new insights on CSLA and Castle:
You talk about "custom class", then, you need to talk about CSLA. It is really necessary to re-realize all CSLA via spring.net AOP.

pure ajax and Castle: Castle is right, if you use pure ajax, why bother asp?!

Use Siebel as the core, integrated it with other similar web-based software, and customize it with in-house modules that use spring.net and ajax

Use Siebel as the core, integrated it with other similar web-based software, and customize it with in-house modules that use spring.net and ajax

By doing this, users immediately have something to experiment with. Also, Siebel will determine the architecture as web-based (since it is highly interactive, even it is via ActiveX, so, it also determines Ajax), and ubiquitously using web services (because of Siebel's EAI methods).

Further (I know I repeated this a lot in my recent blogs -- I am trying to rationalize a new mode of development), after a team working with Siebel's configuration and customization, the team then can really understand what "enterprise application" mean, and will totally give up those VB6 mindsets, and accept Java mindset -- I know Siebel is in C++; but C++ and Java are close enough. In enterprise development, you strive to make all things just like Siebel: every enterprise development is to make a general configurable system; also, every application development is API development.

More specifically, Siebel will lead to the adoption of centralized security and logging, generalized validation, OR mapping, and UI regularity as easy as "let's do something to make the work like working on Siebel" -- Siebel is so good, you cannot argue against that!

Another justification of this Siebel-first approach is that we start from CRM, then, ERP -- this is a micro-relive of the e-business IT revolution. That is actually how Siebel has been growing.

siebel links

edelivery.oracle.com
license.keys.oracle.com (1 month)
8.0.0.0.media pack (40G)
8.0.0.1. patch

supportweb.siebel.com bookshelf
-- installation guide
-- deployment planning guide
-- performance & scalability guide
-------
-- release notes
-- maintenance release guide
-- system requirements & supported platforms
-- tech notes
-- siebel alerts


siebel data model reference (it has FK, but note that the FKs are not enforced in database).

OR mapping in Siebel

OR mapping in Siebel

OK, I lied, I am not sure whether Siebel really has OR mapping internally.

However, to understand it for configuring and customizing it, you should know OR mapping concept: in configuring it, you are effectively configuring the OR mapping; further, it is UI-O-R mapping -- i.e., Siebel makes the UI highly regular, as a result, the mapping is three way, and this three way mapping is actually the core for Siebel.

Once you make the UI highly regular, then, UI-O is really easy. So, the core of the core is back to OR mapping.

As a result, it has all those interesting stuff when you talk about OR mapping. For example, "party" is basically a parent class. It has 1-1 extensions. It also has 1-m relations.

It also has all those concepts such as lookup-table ("master data") and transaction-table ("customer data"). For security, you have user-position-organization-division. Also, those "user keys" concept for non-surrogate composite keys.

Note that the starting point of all those is that you do not think the so-called "behavior". Data, data, data, that is all it is about, just different layers.

There are behaviors, in entities and in facades; however, they are secondary -- SOA, REST, "configuration", OR mapping, all point to the same direction: pay attention to data, not behaviors -- antique OO is more and more irrelevant.

Siebel development environment

Siebel development environment

It is an odd thing: Siebel development environment is similar to its offline mode. It uses a local database.

You could set up a server on your development machine. However, that machine must be a window 2003 server. You can hack it on XP, but it is hack.

html editors for Siebel

Believe it or not, you need an external editor for Siebel development/configuration/customization.
Of course, Vim is good, notepad2, notepad++ are good.

The best? NVU.

a bug in siebel tool and the work around

If you drag a text field from toolbar, it cannot align correctly.
Work around: do not use toolbar, just copy another one on the screen.
or, create another control, then, use that control, instead of text field.

Use Siebel as part of the source of your architecture ideas and spring.net and ajax

Use Siebel as part of the source of your architecture ideas

1. As explained in my previous blog, Siebel is pretty good -- even it has its "weirdness".
2. The special thing about Siebel is that its UI has strict rules corresponding to its entities and facades. It can do that because its UIs have strict rules -- sometimes counter-intuitive, but general and powerful.
3. Other than that, Siebel is basically a proprietary "close-to-best-practices" for all other things ("8 core techniques"), including centralized security, logging, validation, and even OR mapping, and it does not use stored procedures (and even not FKs! -- that is too extreme though).
4. As a result, Siebel is worth it to be a source of your architecture.
5. Further, once you use Siebel, it is inevitable that it will influence your architecture. You have to build other things to inter-operate with it.
6. The key of using Siebel as the source of your architecture, but not just "copy" it, is to abstract it into "8 core techniques" -- then, it is obvious that we should use spring.net and ajax.

Sunday, August 26, 2007

Oracle Stored Procedures examples and notes

Oracle Stored Procedures examples and notes

I used SP for a long time; then, stopped using it; then, used it again, then, stopped, then, again ... you got the idea. It seems that it will be a while that we can say we will never use it for ordinary development, and it will certainly be here "forever" for special situations. So, here are the minimalist examples and notes.

My stand of using SP? Do not use it if you can use OR mapping, or, if it is a new project (even you do not use OR mapping -- and in that case, non-parameterized sqls are also fine -- as long as you parse the sql to prevent sql injection -- you need to parse it for the single quote anyway. Remember, developer productivity is number one, everything else should be treated as explicit feature request); however, it does not hurt that much, just a little bit waste.

The key to prevent SP from being harmful is to keep it super simple. It should be purely a pure thin wrapper of CRUD sqls.

The following has more info than necessary; however, it is clear that the following shows the minimalist CRUD approach.

-------------------------------CRUD examples
-------------------------------
-------------------------------
http://www.devshed.com/c/a/Oracle/Developing-Simple-PL-SQL-Stored-Procedures-for-CRUD-Operations/1/
http://www.c-sharpcorner.com/UploadFile/john_charles/CallingOraclestoredproceduresfromMicrosoftdotNET06222007142805PM/CallingOraclestoredproceduresfromMicrosoftdotNET.aspx

---------------insert

create or replace procedure p_emp_insert (p_empno emp.empno%type,
p_ename emp.ename%type, p_sal emp.sal%type, p_deptno emp.deptno%
type) as
begin
insert into emp
(
empno,
ename,
sal,
deptno
)
values
(
p_empno,
p_ename,
p_sal,
p_deptno
);
Commit;
exception
when dup_val_on_index then
raise_application_error(-20001, 'Employee already
exists');
when others then
raise_application_error(-20011, sqlerrm);
end;
/
---------------we could add validation in the above SP, but do we really want to do that? My vote is no. We do not want that! validation should be the responsibility of facade and entity.

create or replace procedure p_emp_insert (p_empno emp.empno%type,
p_ename emp.ename%type, p_sal emp.sal%type, p_deptno emp.deptno%
type) as
Invalid_sal exception;
Invalid_deptno exception;
begin
if p_sal<100>10000 then
raise invalid_sal;
end if;


declare
dummy_var varchar(10);
begin
select 'exists' into dummy_var
from dept
where deptno = p_deptno;
exception
when no_data_found then
raise Invalid_deptno;
when others then
raise_application_error(-20011, sqlerrm);
end;


insert into emp
(
empno,
ename,
sal,
deptno
)
values
(
p_empno,
p_ename,
p_sal,
p_deptno
);
Commit;
exception
when invalid_sal then
raise_application_error(-20001, 'Salary must be in
between 100 and 10000');
when invalid_deptno then
raise_application_error(-20001, 'Department doesn't
exist');
when dup_val_on_index then
raise_application_error(-20001, 'Employee already
exists');
when others then
raise_application_error(-20011, sqlerrm);
end;
/
---------------update

create or replace procedure p_emp_update (p_empno emp.empno%type,
p_ename emp.ename%type, p_sal emp.sal%type, p_deptno emp.deptno%
type) as
Invalid_sal exception;
Invalid_deptno exception;
Invalid_empno exception;
begin
if p_sal<100>10000 then
raise invalid_sal;
end if;
declare
dummy_var varchar(10);
begin
select 'exists' into dummy_var
from dept
where deptno = p_deptno;
exception
when no_data_found then
raise Invalid_deptno;
when others then
raise_application_error(-20011, sqlerrm);
end;
update emp set
ename=p_ename,
sal=p_sal,
deptno=p_deptno
where empno=p_empno;
if sql%notfound or sql%rowcount=0 then
rollback;
raise Invalid_empno;
end if;
commit;
exception
when invalid_sal then
raise_application_error(-20001, 'Salary must be in
between 100 and 10000');
when invalid_deptno then
raise_application_error(-20001, 'Department doesn't
exist');
when invalid_empno then
raise_application_error(-20001, 'Employee does not
exist');
when others then
raise_application_error(-20011, sqlerrm);
end;
/
---------------delete

create or replace procedure p_emp_delete (p_empno emp.empno%type) as
Invalid_empno exception;
begin
delete from emp
where empno=p_empno;
if sql%notfound or sql%rowcount=0 then
rollback;
raise Invalid_empno;
end if;
commit;
exception
when invalid_empno then
raise_application_error(-20001, 'Employee does not
exist');
when others then
raise_application_error(-20011, sqlerrm);
end;
/
---------------select without ref cursors

create or replace procedure p_emp_details(p_empno emp.empno%type,

p_ename OUT emp.ename%type, p_sal OUT emp.sal%type, p_deptno OUT
emp.deptno%type)
as
begin
select ename, sal, deptno
into p_ename, p_sal, p_deptno
from emp
where empno = p_empno;
exception
when no_data_found then
raise_application_error(-20001, 'Employee not
found');
when too_many_rows then
/* this would not happen generally */
raise_application_error(-20002, 'More employees exist
with the same number');
when others then
raise_application_error(-20003, SQLERRM);
end;
/
----------driver of the above sp:

declare
s emp.sal%type;
en emp.ename%type;
d emp.deptno%type;
begin
p_emp_details(7369, en,s,d);
dbms_output.put_line('name of employee: ' || en);
dbms_output.put_line('Salary: ' || s);
dbms_output.put_line('Deptno: '||d);
end;
/


---------------example of select without ref cursors

create or replace procedure count_emp_by_dept(pin_deptno number, pout_count out number)
is
begin
select count(*) into pout_count
from scott.emp
where deptno=pin_deptno;
end count_emp_by_dept;

------

Using System;

using System.Collections.Generic;

using System.Text;

using System.Data.OracleClient;

using System.Data;



namespace CallingOracleStoredProc

{

class Program

{

static void Main(string[] args)

{

using (OracleConnection objConn = new OracleConnection("Data Source=ORCL; User ID=scott; Password=tiger"))

{

OracleCommand objCmd = new OracleCommand();

objCmd.Connection = objConn;

objCmd.CommandText = "count_emp_by_dept";

objCmd.CommandType = CommandType.StoredProcedure;

objCmd.Parameters.Add("pin_deptno", OracleType.Number).Value = 20;

objCmd.Parameters.Add("pout_count", OracleType.Number).Direction = ParameterDirection.Output;



try

{

objConn.Open();

objCmd.ExecuteNonQuery();

System.Console.WriteLine("Number of employees in department 20 is {0}", objCmd.Parameters["pout_count"].Value);

}

catch (Exception ex)

{

System.Console.WriteLine("Exception: {0}",ex.ToString());

}



objConn.Close();

}

}

}

}

--------------another example select without ref cursors, with a function

create or replace function get_count_emp_by_dept(pin_deptno number)
return number
is
var_count number;
begin
select count(*) into var_count
from scott.emp
where deptno=pin_deptno;
return var_count;
end get_count_emp_by_dept;

---------note it uses "return_value" as the parameter name

using System;

using System.Collections.Generic;

using System.Text;

using System.Data.OracleClient;

using System.Data;



namespace CallingOracleStoredProc

{

class Program

{

static void Main(string[] args)

{

using (OracleConnection objConn = new OracleConnection("Data Source=ORCL; User ID=scott; Password=tiger"))

{

OracleCommand objCmd = new OracleCommand();

objCmd.Connection = objConn;

objCmd.CommandText = "get_count_emp_by_dept";

objCmd.CommandType = CommandType.StoredProcedure;

objCmd.Parameters.Add("pin_deptno", OracleType.Number).Value = 20;

objCmd.Parameters.Add("return_value", OracleType.Number).Direction = ParameterDirection.ReturnValue;



try

{

objConn.Open();

objCmd.ExecuteNonQuery();

System.Console.WriteLine("Number of employees in department 20 is {0}", objCmd.Parameters["return_value"].Value);

}

catch (Exception ex)

{

System.Console.WriteLine("Exception: {0}",ex.ToString());

}



objConn.Close();

}

}

}

}

---------------use select with ref cursors

create or replace package human_resources
as
type t_cursor is ref cursor;
procedure get_employee(cur_employees out t_cursor);
end human_resources;

-------
create or replace package body human_resources
as
procedure get_employee(cur_employees out t_cursor)
is
begin
open cur_employees for select * from emp;
end get_employee;
end human_resources;


------
Using System;

using System.Collections.Generic;

using System.Text;

using System.Data.OracleClient;

using System.Data;



namespace CallingOracleStoredProc

{

class Program

{

private static void prvPrintReader(OracleDataReader objReader)

{

for (int i = 0; i < i =" 0;" objconn =" new" source="ORCL;" id="scott;" password="tiger" objcmd =" new" connection =" objConn;" commandtext = "human_resources.get_employee" commandtype =" CommandType.StoredProcedure;" direction =" ParameterDirection.Output;" objreader =" objCmd.ExecuteReader();" i =" 0;" i =" 0;" objconn =" new" source="ORCL;" id="scott;" password="tiger" objcmd =" new" connection =" objConn;" commandtext = "human_resources.get_employee_department" commandtype =" CommandType.StoredProcedure;" direction =" ParameterDirection.Output;" direction =" ParameterDirection.Output;" objreader =" objCmd.ExecuteReader();" ename="p_ename," job="p_job," mgr="p_mgr," hiredate="p_hiredate," sal="p_sal," comm="p_comm," deptno="p_deptno" empno="p_empno;" empno="p_empno;" objconn =" new" source="ORCL;" id="scott;" password="tiger" objadapter =" new" objselectcmd =" new" connection =" objConn;" commandtext = "human_resources.select_employee" commandtype =" CommandType.StoredProcedure;" direction =" ParameterDirection.Output;" selectcommand =" objSelectCmd;" objinsertcmd =" new" connection =" objConn;" commandtext = "human_resources.insert_employee" commandtype =" CommandType.StoredProcedure;" insertcommand =" objInsertCmd;" objupdatecmd =" new" connection =" objConn;" commandtext = "human_resources.update_employee" commandtype =" CommandType.StoredProcedure;" updatecommand =" objUpdateCmd;" objdeletecmd =" new" connection =" objConn;" commandtext = "human_resources.delete_employee" commandtype =" CommandType.StoredProcedure;" deletecommand =" objDeleteCmd;" dtemp =" new" count =" {0}" deptno =" p_deptno" p_deptno =""> 30,
p_recordset => v_cursor);

LOOP
FETCH v_cursor
INTO v_ename, v_empno, v_deptno;
EXIT WHEN v_cursor%NOTFOUND;
DBMS_OUTPUT.PUT_LINE(v_ename || ' | ' || v_empno || ' | ' || v_deptno);
END LOOP;
CLOSE v_cursor;
END;
/

-------vb.net

Dim conn, cmd, rs

Set conn = Server.CreateObject("adodb.connection")
conn.Open "DSN=TSH1;UID=scott;PWD=tiger"

Set cmd = Server.CreateObject ("ADODB.Command")
Set cmd.ActiveConnection = conn
cmd.CommandText = "GetEmpRS"
cmd.CommandType = 4 'adCmdStoredProc

Dim param1
Set param1 = cmd.CreateParameter ("deptno", adInteger, adParamInput)
cmd.Parameters.Append param1
param1.Value = 30

Set rs = cmd.Execute

Do Until rs.BOF Or rs.EOF
-- Do something
rs.MoveNext
Loop

rs.Close
conn.Close
Set rs = nothing
Set param1 = nothing
Set cmd = nothing

Set conn = nothing


---------------strong typed ref cursor

create or replace package REFCURSOR_PKG as
TYPE WEAK8i_REF_CURSOR IS REF CURSOR;
TYPE STRONG REF_CURSOR IS REF CURSOR RETURN EMP%ROWTYPE;
end REFCURSOR_PKG;


-------------another example with VB.net code
CREATE OR REPLACE PACKAGE curspkg_join AS
TYPE t_cursor IS REF CURSOR ;
Procedure open_join_cursor1 (n_EMPNO IN NUMBER, io_cursor IN OUT t_cursor);
END curspkg_join;
/

CREATE OR REPLACE PACKAGE BODY curspkg_join AS
Procedure open_join_cursor1 (n_EMPNO IN NUMBER, io_cursor IN OUT t_cursor)
IS
v_cursor t_cursor;
BEGIN
IF n_EMPNO <> 0
THEN
OPEN v_cursor FOR
SELECT EMP.EMPNO, EMP.ENAME, DEPT.DEPTNO, DEPT.DNAME
FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO
AND EMP.EMPNO = n_EMPNO;

ELSE
OPEN v_cursor FOR
SELECT EMP.EMPNO, EMP.ENAME, DEPT.DEPTNO, DEPT.DNAME
FROM EMP, DEPT
WHERE EMP.DEPTNO = DEPT.DEPTNO;

END IF;
io_cursor := v_cursor;
END open_join_cursor1;
END curspkg_join;
-------------

Imports System.Data.OracleClient

Dim Oraclecon As New OracleConnection("Password=pwd;" & _
"User ID=uid;Data Source=MyOracle;")
Oraclecon.Open()

Dim myCMD As New OracleCommand()
myCMD.Connection = Oraclecon
myCMD.CommandText = "curspkg_join.open_join_cursor1"
myCMD.CommandType = CommandType.StoredProcedure
myCMD.Parameters.Add(New OracleParameter("io_cursor", OracleType.Cursor)).Direction = ParameterDirection.Output
myCMD.Parameters.Add("n_Empno", OracleType.Number, 4).Value = 123
Dim myReader As OracleDataReader
Try
myCMD.ExecuteNonQuery()
Catch myex As Exception
MsgBox(myex.Message)
End Try

myReader = myCMD.Parameters("io_cursor").Value

Dim x, count As Integer

count = 0

Do While myReader.Read()
For x = 0 To myReader.FieldCount - 1
Console.Write(myReader(x) & " ")
Next
Console.WriteLine()
count += 1
Loop

MsgBox(count & " Rows Returned.")

myReader.Close()
Oraclecon.Close()


/





-----------rowtype

declare
type r_cursor is REF CURSOR;
c_emp r_cursor;
er emp%rowtype;
begin
open c_emp for select * from emp;
loop
fetch c_emp into er;
exit when c_emp%notfound;
dbms_output.put_line(er.ename || ' - ' || er.sal);
end loop;
close c_emp;
end;
---------- "record"

declare
type r_cursor is REF CURSOR;
c_emp r_cursor;
type rec_emp is record
(
name varchar2(20),
sal number(6)
);
er rec_emp;
begin
open c_emp for select ename,sal from emp;
loop
fetch c_emp into er;
exit when c_emp%notfound;
dbms_output.put_line(er.name || ' - ' || er.sal);
end loop;
close c_emp;
end;

------------ref cursor is dynamic

------------(this is crucial for practical use in SP)

declare
type r_cursor is REF CURSOR;
c_emp r_cursor;
type rec_emp is record
(
name varchar2(20),
sal number(6)
);
er rec_emp;
begin
open c_emp for select ename,sal from emp where deptno = 10;
dbms_output.put_line('Department: 10');
dbms_output.put_line('--------------');
loop
fetch c_emp into er;
exit when c_emp%notfound;
dbms_output.put_line(er.name || ' - ' || er.sal);
end loop;
close c_emp;
open c_emp for select ename,sal from emp where deptno = 20;
dbms_output.put_line('Department: 20');
dbms_output.put_line('--------------');
loop
fetch c_emp into er;
exit when c_emp%notfound;
dbms_output.put_line(er.name || ' - ' || er.sal);
end loop;
close c_emp;
end;
--------------ref cursor within a loop

declare
type r_cursor is REF CURSOR;
c_emp r_cursor;
type rec_emp is record
(
name varchar2(20),
sal number(6)
);
er rec_emp;
begin
for i in (select deptno,dname from dept)
loop
open c_emp for select ename,sal from emp where deptno = i.deptno;
dbms_output.put_line(i.dname);
dbms_output.put_line('--------------');
loop
fetch c_emp into er;
exit when c_emp%notfound;
dbms_output.put_line(er.name || ' - ' || er.sal);
end loop;
close c_emp;
end loop;
end;

-----------------nested proc (it is like class's static method. it is just like package)

declare
type r_cursor is REF CURSOR;
c_emp r_cursor;
type rec_emp is record
(
name varchar2(20),
sal number(6)
);
er rec_emp;
procedure PrintEmployeeDetails is
begin
loop
fetch c_emp into er;
exit when c_emp%notfound;
dbms_output.put_line(er.name || ' - ' || er.sal);
end loop;
end;
begin
for i in (select deptno,dname from dept)
loop
open c_emp for select ename,sal from emp where deptno = i.deptno;
dbms_output.put_line(i.dname);
dbms_output.put_line('--------------');
PrintEmployeeDetails;
close c_emp;
end loop;
end;

------------------by passing parameters, we can move the print proc outside

declare
type r_cursor is REF CURSOR;
c_emp r_cursor;
type rec_emp is record
(
name varchar2(20),
sal number(6)
);
procedure PrintEmployeeDetails(p_emp r_cursor) is
er rec_emp;
begin
loop
fetch p_emp into er;
exit when p_emp%notfound;
dbms_output.put_line(er.name || ' - ' || er.sal);
end loop;
end;
begin
for i in (select deptno,dname from dept)
loop
open c_emp for select ename,sal from emp where deptno = i.deptno;
dbms_output.put_line(i.dname);
dbms_output.put_line('--------------');
PrintEmployeeDetails(c_emp);
close c_emp;
end loop;
end;





-------------------------------notes
-------------------------------
-------------------------------
-------------------------------

A. Environment

1. create or replace will keep all grants, so use it, instead of drop then create again
2. execute PPP.XXXX('para1'); or BEGIN addtuple1(99); END; . then \
3. errors is in user_errors

(in sqlplus: show errors procedure ;

4. source is in all_source (or dba_source), user_objects

5. sometimes need to recompile: alter procedure/package XXXX compile

6. sqlplus: "." (period) means the end
7. sqlplus: "/" means "run;"


B. Package, Procedures
1. always use package to organize procedures, as namespace.
2. also, package has an extra feature: it is like static class, its static initializer is at the bottom of the body: immediately before the end, you add a begin block for package initializer.
3. note that "package body" is the meat; package itself is just a useless trace of C++ heritage.
4. in package body, you put pl/sql block. A block always has: declare (optional), begin, exception (optional), end.
5. in exception section: you use "when ZERO_DIVIDE, then", you can use "when others". To raise exception, you can use "RAISE" (typically used outside exception section, to handle it yourself in the SP's exception section later), or (to let it bubble up by the system), RAISE_APPLICATION_ERROR (from -20001 to -20999)
6. in command section: you can use if-then-elsif-then-else, and loop (exit when, or, while XXX, or, for-XXX-in).
7. The most interesting thing is its cursor related stuff: <======================= (a) a cursor is just like a "reader" in ADO. For example, we can declare: "cursor rad_cursor is select * from RADIUS_VALS". <======================================== (b) note that rad_cursor is an instance (not a type); however, we can have a type based on the instance: ----(i) rad_val rad_cursor%ROWTYPE; ----(ii) radius rad_val.Radius%TYPE; (c) to loop through a cursor, we can use simplified syntax, so that we do not need to write open, fetch-XX-into-YY, and close, or test rad_cursor%NOTFOUND (or rad_cursor%ROWCOUNT), we simply say: "for rad_val in rad_cursor". (d) in the loop, we can have some pl/sql's special sqls. For example: ----SELECT e,f INTO a,b FROM T1 WHERE e>1;
----DELETE FROM T1 WHERE CURRENT OF T1Cursor;

(e) note: (b)(c)(d) are not really necessary if you do things right. All we really need is to wrap basic CRUD sqls with SPs, with absolutely no processing (i.e. logic) at all (the so-called "data logic" is really just performance optimization -- as a result, in normal development, we do not even think about it -- we deal with it with systematic measurement etc. In general, in almost all projects, if you do it right, you do not need to do any "data logic" optimizations).



C. Other things like Functions, Triggers, etc.
----. comment /* */
----. usually we use procedures (use out parameter for return values), not functions. However, function can return a value. Function can be used in sql (it should well-behaved, i.e., no out parameter, it should not change things).
----. trigger naming convention: BU_ROW_XXXXXX, "B" means before, "U" means update, "ROW" means row-level, XXXX for table name. We can combine I and U etc, in the body, we can use "if inserting than" to differentiate them.
----. trigger can be triggered by a column; further, we use "when" to add extra conditions to be triggered.
----. in trigger, we can use :new.YYY, :old.XXX to get the column values.


Saturday, August 25, 2007

Siebel CRM: technical and process

Siebel CRM: technical and process

A. Technical:

1. ActiveX, instead of Ajax: Siebel CRM (8.0) is web based. It does not use Ajax, instead, it uses two modes, one is "high interactive" mode, which uses ActiveX; another one is for non-IE clients, uses "standard mode", which uses pre-ajax stuff. It is said that it used java applet before activeX (that is why those ActiveXs are still called "applet" in Siebel), then, because java was too slow, so, java was replaced by ActiveX. Obviously, it is a wrong decision that ajax is not used.

2. Siebel UI is a little bit less intuitive than ordinary web or window applications. However, by doing this, it enables its UIs to be generic enough to handle complex situations systematically.
(i) For example, it uses command menus, instead of command buttons.
(ii) Also, it uses a pattern: select a node on the left-side-tree-view, to get the right-side-list-view, then, select a row on the right-side-list, then, select a child node on the left-side-tree (usually, this step should happen on the right-side, by a child list), then, the right-side will have a child list to show the content of the child node.
(iii) Another example is that all UIs are always made of two "applets" (that is, in addition to the tree): "list" (i.e., grid), "form" (many label+text boxes/drop down menus) , plus some tabs or links (category tabs, view tabs, and screen tabs) -- you can put the list "applet" on top, then, this is the "aggregate view" style (users are familiar with this view; because they are used in all ordinary web sites); you can also put the form "applet" on top, then, it is the "detailed view" -- however, in this situation, this view is counter-intuitive, because most users expect to see a three-tier view: the grand-parent at the top, then, the parent, then, the grand-children.
(iv) Also, in the "high interactive" mode, it uses in-place editing, and uses in-place editing-like style to do searching. In ordinary web application, editing uses the form "applet"; further, searching also uses the form "applet".

Those things are not intuitive, further, some are not necessary -- not using them can make Siebel UIs more intuitive and still be generic -- however, as a whole, they are good enough, and they make the following "mapping" possible:

"applet" -- entity objects (in Siebel, entities are called "business components")
"view" -- facade objects (in Siebel, facades are called "business objects")

3. Siebel facades are in a proprietary application server. Actually, its UIs are also in the app server. The generic "web server" is still used though, mostly for load balancing. As a result, for integration, web service is used to get data from those facades.

4. Another surprise about Siebel is that its database does not even enforce FKs. FK are enforced in its facades and entities.


Some thoughts:

On the one hand, after understanding the details of Siebel, I appreciate more about the statement that in the world of lightweight (i.e., no entity bean, but OR mapping) java and .net, Siebel is too expensive for its value. As long as you have an experienced team lead (or architect) so that you know how to say no to unreasonable non-essential UI features and know how to use OR mapping, systematic Ajax with databinding, centralized security and logging (and transaction and networking), and validation, then, the difference between creating your own application and configuring Siebel is not that big.

On the other hand, I do see the value of saying no to unreasonable non-essential UI features, and OR mapping, systematic Ajax with databinding, centralized security and logging (and transaction and networking), and validation. If you can do those things right and fast, then, it is worth millions!


B. Process:

Siebel 's success also points out that it is important to have a working prototype. This is the major advantage of on-shelf software. For an enterprise level application that usually will take two or three years, you can demo a prototype immediately, and then put it to user's hands within a few weeks or a few months.

However, it is amazing to hear that you need produce large amount of documents before implementing Siebel. I do not believe it. I believe it is crap. The key of using Siebel is to do some preliminary research (and "requirement gathering) to decide to use Siebel, then, use a few weeks to set it up and use it. Then, fine tune it, configure it, and even customized it. Of course, we need to document along the process; however, heavy weight upfront documentation without letting users try Siebel out is simply wrong.

domain modeling, concept analysis, knowledge structure, ontology, "applying" knowledge and faith

domain modeling, concept analysis, knowledge structure, ontology, "applying" knowledge and faith

This blog is try to expand the perspective of "8 core techniques" + "3 questions" (high-level use cases, uses cases, domain model). More accurately, it is to expand "3 questions", because it is "3 questions" that expands "8 core techniques" into business process perspective. In this blog, I will continue to expand that into everyday life.

There are two questions: (a) can domain modeling be used as a general concept analysis tool? -- perhaps we need a concept of "knowledge structure"; (b) everything is knowledge, is that really true?

(a) Let's say, can we apply domain modeling in physics study? Putting it that way, to be frank, I doubt it. However, how about computational physics? Then, the difference between "ordinary" physics and computational physics? I believe there are three elements here.
(i) In domain modeling, the key is the multiplicity. Is multiplicity the key for other concept analysis? I really doubt it. However, is multiplicity really the whole story of domain analysis? No. Further, having a sense of multiplicity will help qualitative analysis.
(ii) It seems that when we do "ordinary" concept analysis, we tend to blur the border between the reality and the concept, i.e., the representation of the reality. It is not a good habit. When we do "domain modeling", we know the difference, because we know we are doing data modeling or in-memory-object modeling. However, "data" or "in-memory-object" are obvious too nerdy, too computer/software-centric. So, I believe "knowledge structure" (or, "ontology") is a good concept. It is more tangible than "concept analysis", and therefore can remind us the border between reality and the representation of reality, while it can be applied to "wet" brain, and used naturally everywhere and not (too) nerdy.
(iii) From academic point of view, "knowledge structure" should be a important concept in philosophy, more specifically, ontology, philosophy of language, philosophy of science, metaphysics, epistemology, and, my favorite (seriously, perhaps someday I will go back to study of psychology) psychology of sleep: http://pespmc1.vub.ac.be/KNOWSTRUC.html (the result of the googling after I wrote this blog).

more links from googling "ontology"

http://en.wikipedia.org/wiki/Ontology
http://ontology.buffalo.edu/
http://www-ksl.stanford.edu/kst/what-is-an-ontology.html
http://www.jfsowa.com/ontology/

---------------- a quote from wikipedia about the differences between the ontology studies of computer science and philosophy

What ontology has in common in both computer science and philosophy is the representation of entities, ideas, and events, along with their properties and relations, according to a system of categories. In both fields, one finds considerable work on problems of ontological relativity (e.g. Quine and Kripke in philosophy, Sowa and Guarino in computer science (Top-level ontological categories. By: Sowa, John F. In International Journal of Human-Computer Studies, v. 43 (November/December 1995) p. 669-85.), and debates concerning whether a normative ontology is viable (e.g. debates over foundationalism in philosophy, debates over the Cyc project in AI).

Differences between the two are largely matters of focus. Philosophers are less concerned with establishing fixed, controlled vocabularies than are researchers in computer science, while computer scientists are less involved in discussions of first principles (such as debating whether there are such things as fixed essences, or whether entities must be ontologically more primary than processes). During the second half of the 20th century, philosophers extensively debated the possible methods or approaches to building ontologies, without actually building any very elaborate ontologies themselves. By contrast, computer scientists were building some large and robust ontologies (such as WordNet and Cyc) with comparatively little debate over how they were built.

--------------------------

(b) Let's say that we use "knowledge structure" (ontology) everywhere, but can we really do it in art experience, or, even better, religious experiences? Note that I am referencing to "experiences", not art theory/aesthetics or theology -- they can be treated as knowledge, obviously. This is just another form of the difference between reality and the representation of reality -- but more directly, and cannot be "postponed" anymore. By "postponed" I mean, in other places, for example, in technology or engineering or mathematics, or even business, we can "postpone" the differences between "reality" and "knowledge of reality" by "transforming" ("learning") "reality" to "knowledge of reality" -- it seems that it is OK that we do that -- actually, most of the time, in our more and more sophisticated world, it seems that it is the preferred way to do that -- when you do something, you must know what you are doing, do not "just do it".


However, in art it is not the case; it it even more "not the case" in the faith life (or "religious life" -- but it seems that "faith life" has a more positive tone).

It seems that knowledge and faith are not symmetric. Knowledge is a space-like, while faith is a singularity -- when you begin to talk about faith, then, the content of your talk is transformed into knowledge!

However, the singularity is the most active part of our life. Put it in another way, it is the "engine" of the "learning", and more importantly, "applying", of the huge space of knowledge -- obviously, you'd better "oil" the engine nicely!

OK, this blog is (still) a technical one, as result (and purely so), the point I am trying to make here is not about the faith life -- that is personal -- it is about "knowledge structure": except one and only one singularity that we cannot really talk (whenever we talk, it is changed into knowledge), everything is knowledge; consequently, everything can be covered by the concept of "knowledge structure". As a result, let's use "ontology" more often.

Saturday, August 18, 2007

Why and How to use server side ajax -- even you do not like it

Why and How to use server side ajax -- even you do not like it


Think about it, SP now is not that harmful, because we all accept the statement "never put (business) logic in SP" -- this is the way to "neutralize" SP (if you realize that all "data logic" belongs to "business logic" -- other than performance optimization -- then, you basically have nailed SP to nothing!) . We need to find the equivalent thing in server side ajax.

The key of using server side ajax is to understand the two sides:

1. "Configuring" via XML is not necessary, but for now (pre-Orcas) it is indeed a little bit simpler than javascript.

2. The harm is that you do not know when to stop, and continue to hack features on the server side, while it is really easy to do it via javascript API of those server side controls.

So, the key is to remember the javascript API of those server side controls.

Why and How to use stored procedures -- even you do not like them

Why and How to use stored procedures -- even you do not like them

1. Stored procedures certainly have their values. For example, when you do not use web services, and you have multiple-platforms, stored procedures provide all the benefits of web services. As a matter of fact, web services (or application servers) are simply stored-procedures-moved-out-from-databases.


2. However, in everyday development, it is antique practice to do stored procedures. I know, M$ marketing and some tutorial demo people are still recommending it; but if you take the words from marketing people or tutorial people as your engineering guidelines, then, you are kidding yourself!

3. The real valid reason of using stored procedures is consistency. If you are in a M$ shop, and if there are a lot of code using SP, and people are used to using SP, then, you have to use it -- until there is a big project that you can break the obsolete tradition (I will explain when next).

4. The above reason also implies that SP does not really hurt that much, it is just a little bit waste. As a result, you should not be too enthusiastic about removing SP. You must choose your battle, concentrate on making productive changes that really benefit the team, not making those purposeless changes.

5. Then, when should you push really hard to eliminate the SP practice? When you use OR mapping! Until then, keep using SP -- it is harmless for now.

6. Of course, you should not put logic in SP; or, relaxing it a little bit, you can put "data logic" in SP -- frankly, it is really a political compromise; for my taste, absolutely no logic at all -- the whole SP will go away, why bother to think about where to draw the line between "data logic" and "business logic", crazy. If you think about it, "data logic" is really just a performance optimization concept. As a result, using it as everyday practice guideline is really counterproductive.

Too many technologies, framework or not and aop, and spring.net

Too many technologies, framework or not and aop, and spring.net

A. It is a common feeling that M$ offers too many technologies. This is especially troublesome for team leadership -- some "new" developers keep introducing stuff, all M$ "recommended".

To deal with it, we have to say: you cannot use new technologies, just because you can and they are new. They must be relevant and make sense.

I go further. Using new technologies must fit into two categories: it directly meet users' needs of certain features, or, it solves the issues that the "8 core techniques" try to solve.

(1) The core of the core? coarse-grained AOP, of course: centralized security, logging, transaction, and networking.

(2) Below it, the logging (implementation) and database acess.

(3) Above it, fine-grained AOP (entity logic-validation), and MVC (or, MVPC) -- i.e., databinding.

If a new technology does not help solving those problems (and not directly address a feature needed by users), then, forget about it.

B. Framework or not

(1) The key is how effective a coding guideline or an architecture guideline can be. My bet is that they rarely work! You cannot solve an engineering issue by using pure managerial techniques. You must "automate" the "guidelines", which is a framework!

-- The only real effective guidelines are those that enforced by a framework.

(2) Another key is how fast you can get implement features in security, logging, transaction, networking (and validation), with reasonable (acceptable) quality. My experience is that you rarely can, without a framework.

-- The only fast and easy way to implement reliable security, logging, transaction, networking (and validation) is to use a good (and easy) framework. -- note that here, a framework helps you get things done faster, not slower!

Note that I backed off from spring.net, because I cannot convince people about this, and I have to accept the consensus at that time. However, it turns out that it all depends on the size of your vision and perspective. If it is large enough (e.g. anything > 7 person-year, no mention a whole enterprise system), then, it should be spring.net.

Also note that I am more and more convinced that AOP is the center here, not IOC or TDD. The key is that AOP is inherently feature-oriented -- you need those security features!

C. choice among Spring.net, castle, M$ entlib 3.0:

(1) needs politically correctness for a M$-only shop: M$ entlib 3.0
(2) likes dynamic new challenges: castle
(3) is pragmatic, mature: spring.net (plus log4net, no need to use M$'s logging)

another set of wording about layering from SOA

UI or service
facade -- processor
dao -- connector
db -- resources ----- I like "resources", it connect to REST: the key concept of REST is that service expose resource directly, "antique OO encapsulation" is not true after all, at least not totally true.

Saturday, August 04, 2007

How to use and participate Open Source

How to use and participate Open Source

For thin frameworks, you must learn to tear them apart; for frameworks that are absolutely necessary, you cannot really tear them apart. However, you can do something close to tearing it part – only use its core, never cut/paste big examples, or, “user extensions”. Gradually, by combining those libraries, you effectively, well tearing them apart.

Yes, I am talking about javascript libraries – they are absolutely necessary, so, you cannot simply tear them apart.


The key is that do not try to cut/paste everything. Once you have a key feature (e.g., a grid in ext), you should stop paying attention to big examples.


---------------------more elaborations
Must: go through all other small tutorial examples, so that you have the ability to search/ask the forum for small pieces of code (not even examples, just a few lines code or even just ideas)

Must NOT: continue looking for/at big examples (you need to do that in the very beginning, to make sure that the whole thing is capable), but you must not try to use it immediately. You must build from scratch at the core-grid level -- prematurely trying to use "user extensions" or "big examples" will actually slow you down.

--------in short: big examples are only for evaluation
--------when development, make sure start from core of the framework!!!

---------------------even more elaboration
I understand the pressure to get something done -- you need cut/past things. However, that kind of pressure will only slow down you, unless what you really need is just some superficial demo (actually, this is a technique to reduce pressure -- offer managers some superficial demos, i.e. download something, make it run, change UI wording by hard-coding the working in UI to make it looks like relevant to what you are doing.

Those demos can be treated as evaluation task. For real development, you need to fine-tune thing, so, you need all details! So, sooner or later, you have to do it. If you do it in the beginning, it is streamlined, much more efficient, and must fewer crises.


By doing the above, even if you "just" use it, you are participating the open source.

Thursday, August 02, 2007

REST -- web service is all about data (or "resource")

REST -- web service is all about data (or "resource")
---- REST and “domain model must follow data model” again, CSLA again, and FIT again

1. Theory or perspective -- REST and data warehouse: REST is just a completion of the data-warehouse vision: it is totally OO crap saying that data should be wrapped. At higher level, data is visible by users – actually, at that level, data is all users cares. Business logic is just a means to reach the data (‘state”).


“Completion”, because data-warehouse only point out the “GET” (or “R” in CRUD”) – via dimensions – users know dimensions.

REST now put all CRUD (“GET”, “POST”, “PUT”, “DELETE”) in the picture. The key is the idempotent feature: GET is automatically that way, DELETE and PUT also, but is tricky, POST you need to do something.

Note you may simply say REST (“resource”) is closer to “document” point of view, and SOAP is closer to “procedure” point of view. However, for most real programmers, “document” is nobody, nothing, null – it cannot invoke any associations and thinking! The only powerful concept here is “data”. We must understand that from a high level point of view, “data” and “document” are the same thing. SOAP wants to hide data; REST want to expose data. Note that the data is not tiny details, but things like “dimensions”!

This is consistent with other data-centric point of views: for high level analysis, talk data. Do not say users do not know data, they know, and data are all they really care!

Also, saying that you cannot create domain model by data model – again, antique OO crap. The opposite is true: the backbone of the domain model must be data model – if not, then, domain model is wrong.


2. Practice -- REST and client-server: REST makes things simpler for client (with JSON, even vb3 and javascript can do it!), but-and-so, it requires more from the servers (so, regular SOAP must be enhanced-i.e.-wrapped, to deal with issues like e.g. the idempotent issue. Note that if idempotent issue only happens if you think data.

3. Summary: Web Service is at higher level than facade. So, it cannot be procedural anymore, it must be resourceful or restful -- it must be like data warehouse's dimensional.

4. It is funny that CSLA has CRUD everywhere, yet most people cannot see that it begs for REST point of view (its mantra is so-called "a class is determined by its behavior" -- antique OO crap!). Also, it has cross-concern regularity everywhere, yet the most people cannot see (or do not want to mention) AOP! CSLA always surprises me.

5. Also, REST makes more sense to FIT – you shall pay attention to data! FIT is all about data, isn’t it?!

the open source way: there are many ways -- at least three -- to do it; be aware

There is a minor issue with ext -- when turning the autosize on, it is slow when there are many -- e.g. > 10 -- columns. So, I will not turn it on. Not a big deal.

However, this reminded me a thing: even it is the best, ext is NOT the only one. Rico is good to get ideas, and YUI is good to get javascript engineering ideas and good documentation about it -- this is because YUI is from Yahoo, and only Yahoo knows how to do javascript engineering; this is especially true for ext, because ext grew out of YUI, so, all Yahoo doc applies to ext almost directly.

So, the following should always be there:

--------------
http://localhost/rico2/rico/examples/asp/ex8.asp
download it, on the example index.html,
and click the online http://dowdybrown.com/dbprod/rico2/examples/php/ex6.php


YUI and jackslocum's old posting when it is YUI-ext and other's posts, e.g.
http://www.rodrigodiniz.qsh.eu/YahooGrid.aspx

Wednesday, August 01, 2007

aptana is crap. Use vim or notepad2, before orcas

Just to be fair, I have to tell the truth: aptana is crap, at least for now.

For now, use Vim (my choice), or, if you are not capable of using vim ;-), use notepad2.
When Orcas comes out, use it.

My guess aptana is targeting poor java programmers, or flash/air programmers: they do not have Oracas ;-)

a. Aptana cannot handle debugging -- you need firebug (or, script debugger if you really hate firefox AND yourself! -- but script debugger does work though, after you configure it right -- just weaker than firebug!).

b. Aptana cannot handle intellisense -- your need your brain for that.

c. Aptana cannot even handle block comment -- you need VS2005.

d. Aptaqn cannot even handle paring braces, brackets, parenthesis (very important for javascript), VS2005 cannot handle them either; but both vim and notepad2 can!

Note: when you do web or other server intensive development, it is very important that you MUST be able to use notepad(2) or vim to do development, at least once for a while (i.e., every time you need to introduce a new thing, set up new stuff, you MUST start from notepad, if you do not, it means you are just a VB6-like clicker, not a programmer), otherwise, you have no way to really understand things -- this is a good interview question for web developer: Do you use a notepad or notepad-like editor other than visual studio, how often? -- of course, most VB6-turned developers fail this question -- believe it or not, they are incapable of using notepad!

summary or simplification of javascript coding style

http://javascript.crockford.com/code.html

summary or simplification of javascript coding style:

1. keys of keys:

a. declare variables in the beginning of the function (like old C style)
(i) this can be important to avoid confusion. Javascript variable has no block scope
---------however, I must add that this is a uphill battle with Java (and now some C# people who have really reinvented themselves from VB6 -- this is a very good interview question for C# people -- if they worked in C# for a while, then, they know; otherwise, they will still use VB6 style) guys. I myself cannot do it. So, I will not do it. I will keep it in mind, but I will do it java style (and modern C++ style also)-- i.e., when I use it, I declare it. I do not declare it before I use it. ---- this actually can help prevent from declaring a variable -- now, it is easy, I always var it; otherwise, I have to check whether I var-ed it or not in the beginning of the function.

b. First line does not start from a new line
(i) this is to avoid semicolon insertion
(ii) which can create the "return null problem" (return null when the value is not the same line with "return")


c.
update: I found another good one: always put "," at the beginning of the line for array elements. This way, you will not forget to add it or remove it when cut/paste. Forget removing ',' is especially bad, becuase firefox is fine, but IE will freak out -- long after you have done the coding!

2. Keys:

a. === and !==: use them most of the time, instead of == and != (also: use the old c trick, 3 === myVarv ------ update: forget about it; does not work! Also, it seems that it is not intuitive, against rule of literate programming. Further, the "===" has a strong psychological effect, you will not use "=" within if anymore! ---- also, within if etc, there should never be valid "=". All those can eliminate the problem -- hepefully).

(i) It is almost always better to use the === and !== operators. The == and != operators do type coercion. In particular, do not use == to compare against falsy values.
(ii) note: if you use ==, if one of them is a number, then, if the other is a string, the string will be changed to a number.

b. + sign as parseInt (+ is necessary because other wise it will be a string if one of them is string!)
total = subtotal + +myInput.value;
is better written as
total = subtotal + (+myInput.value);


3. You must do, but you will remember when you need them:

a. use object.hasOwnProperty(variable) to get the "true members"

for (variable in object) { if (object.hasOwnProperty(variable)) { statements; } }

b. "do" block: it needs ";" (unlike while or for)
(this is important only because we must not forget the ;
because inserting ; by compliler is bad thing -- see above return null issue)

do { statements; } while (condition);

c. "with Statement" -- never use it!

The with statement should not be used.
use a variable, and assign the namespace/class name to the variable:

var o = ooo.eee.oo.ah_ah.ting.tang.walla.walla;
o.bing = true;
o.bang = true;


4. Nice to do:

a. No m_ or _ etc. for private members
---- because javascript has no such concept.
---- sse the right provate mechanism, so that all are provate except the "returned".

b. Braces should be used around all statements as long as it is a compound statement, do not use the one-line version (i.e. no brace version), even for single statements, when they are part of a control structure, such as an if or for statement. This makes it easier to add statements without accidentally introducing bugs.

c. indent 4 spaces, do not use tab.

d. do not use "continue Statement" because it tends to obscure the control flow of the function.

official reasons for using ajax client model -- even in a MS shop

Official reasons for using ajax client model -- even in a MS shop

1. sufficient: Orcas has superb support of javascript; so, soon javascript will be more important than C# !

2. necessary: We can wrap it in server side dlls (i.e. the “server side model”) – some people is doing that. However, whenever there is an even tiny issue, you have to jump many hoops to get there – and there are going to be many issues in the coming one or two years (early days for ajax-stage-2 – MS’s asp ajax and orcas marks the beginning of mass-and-better-ajax, hence, ajax-stage-2). So, for at least one or two years, the client side model is the less-pain approach