Domain Pollution Resolution
0. Domain Word Definition
First I like to clarify the meaning of the “Domain” word used in this text.
The book <<Domain Driven Design>> makes the “Domain” word very hot, and triggered a lot of arguments: what Logic should be placed in the Business Service Layer, what should be placed in the Domain Object itself. This kind of arguments often upgrade to the scope of philosophy, cognitive psychology.
This kind of Domain arguments, are not the focus of this text.
In my opinion, a design can be said as good if it meets these conditions: Polymorphism replaces the hard-coded “if else switch” logic branches, so that when a new requirement comes, it is enough to just add a new class instead of adding “if else switch” logic branches in the existing code; Avoid cross references of packages or classes as much as possible.
This text cares a higher level Domain, similar to the meaning of the Domain used in the Domain Specific Language (DSL).
Following issues will be discussed:
HTML should be only used to describe Structure, right?
HTML should contain logic or not?
HTML should contain server side script logic or not? For example, JSP, Velocity, or Freemarker etc.
HTML should contain server side script logic or not? For example, Java Script etc.
Java code should output HTML tags or not? For example, Taglib, Tapestry Page Component, etc.
Java Code should use Framework-specific HTML View Model? For example, XMLC, Wicket, Echo, etc.
HTTP Web Server is designed as stateless, supporting many users & connections. The current trend of page flow, web flow, continuation at server side, makes the effort to keep the user flow & states in the HTTP Web Server. It is a recommendable way?
SQL is a readable and widely used DSL. To dynamically compose SQL, is always a hard problem.
Java code should embed SQL or not?
Java code should use Criteria API or not?
Script Logic in SQL template should be used or not? For example, iBatis uses XML “if otherwise”; OR Bridge uses velocity.
HQL, OQL introduces the OO feature into the SQL, pretending the underlying is the Object DB instead of Relation DB. It is a recommendable way?
Hibernate changes user class implementation at runtime. It is a recommendable way?
JDO changes user class implementation statically. It is a recommendable way?
Dynamic Proxy, CGLib dynamically changes user class implementation. It is a recommendable way?
Reflection escapes the static type checking. It is a recommendable way?
Thread Local is an implicit contract, instead of the explicit contract (method signature). It is a recommendable way?
These kinds of development mode, code style issues, just like the feeling of Code Small, are quite subjective. So the following statement is not conclusion, instead is just “in my opinion”.
1. HTML Template Layer
HTML should only be used for describing structure, exclusive of all logic.
Server side script logics such as JSP, Velocity, Freemarker are the pollution of Java Code or Script Code to HTML.
Not only Server side script logics such as JSP, Velocity, Freemarker should be excluded, but also Server side script logics such as Java Script.
Of course, it not means giving up Java Script. It just means, not including the Java Script in the HTML. Put the Java Script in to an individual .js file which is to be imported by HTML. Use CSS to connect the HTML Element and Java Script Event Handler.
Following are related materials:
Unobtrusive Javascript
http://www.onlinetools.org/articles/unobtrusivejavascript/
http://www.kryogenix.org/code/browser/aqlists/
http://www.bobbyvandersluis.com/articles/goodpractices.php
How to exclude Server Side Logic from HTML?
Ajax !
Ajax fans must respond quickly by instinct.
Right. Ajax can achieve that effect. The main problem of Ajax is the difficult to use and grasp it.
Any more besides Ajax ?
Several options. XMLC, Jivan, fastm, Wicket, Echo, etc. (and Tapestry?)
fastm is a template tool made by me.
https://fastm.dev.java.net/files/documents/1911/25042/fastm1.0c.zip
fastm uses XML Comment as structure marker. Note, the Structure maker, instead of Logic marker. No “for if else”.
So fastm is not totally free of pollution, just free of logic pollution. fastm just adds the structure marker to HTML. It is not against the original purpose of HTML which is to describe structure.
Ajax , XMLC, Jivan use pure clean HTML. And they have the full control of the HTML structure. You can use code to dynamically control the layout. fastm can do that too. Site mesh, tiles taglib, jsp, velocity, freemarker etc, can not do that.
The fastm samples include a pagination sample, and SQL composition sample.
2. Java Web Layer
Taglib, Tapestry Page Component, Echo, Wicket etc, output the HTML tag in the Java Code, and requires the use of framework-specific HTML View Model in the Java Code. For examples, view objects such as Table, List, Label, Formbean etc. Using these frameworks, the compilation of Java code will depend on these frameworks.
This is the pollution of HTML Tag to Java Code.
JSP, Velocity, Freemarker etc are free of this case. Java Code just provides POJO. The the Server Side Script in the HTML uses these POJO.
Fastm not supports logic, so is a little weaker in this aspect. Fastm requires the Java Code to make logic branches like “if, else” as a Map structure. Since Map exists to the JDK, fastm not requires the Java code to use any framework-specific view model either.
3. Web Layer - Stateless or Stateful
If to support page flow, web flow, continuation in the server side, I would rather to support state in the Browser side. This case should be the best time for Ajax .
I prefer such design: stateless at server side. If state is surely necessary, better keep it in the browser.
Lightweb is a web framework made by me.
https://lightweb.dev.java.net/files/documents/4371/25044/lightweb0.9b.zip
Main features are URL-Centric, Service oriented, Stateless. It supports 3 service models.
Action (like WebWork Action),
Controller (like Spring MVC Controller),
Channel (like Struts Action Dispatcher),
Lightweb supports multiple level module location, uses couples of matching rules instead of a big Site Map config file.
The way of lightweb locating the view, is not like the small state machine way in the Site Map config file (success -> showIt.jsp; fail-> this page), but is to locate the resource directly. lightweb inherits the view of fastm. It regards the template as resource, instead of a executable scriptlet.
Lightweb is designed as IoC-friendly and expose plug-in interface at many points. Programmers have many IoC options. One IoC container managing all, like Spring IoC, Pico, Nano etc; Individual IoC in individual module; IoC in the every Action Validator.
4. ORM Layer
Hibernate dynamically changes user code; JDO statically changes user code.
It reminds me of the Hacker, troy horse, etc. It is the semantic pollution. From the source, you can not see the Domain Object should have such behaviors, but at the runtime, it behaves like that.
iBatis using reflection, and stays innocent, but not very powerful in performance or functions. Some functions require the code generation.
lightor is an ORM make by me.
https://lightor.dev.java.net/files/documents/4370/25043/lightor0.5a.zip
lightor needs the code generation too. The difference is that lightor not Changes any code, just generate New Mapper code. When the Domain Object runs, it is still your original Domain Object. This avoids the semantic pollution.
Mapper code generated by lightor, is able to type-check, read, trace, debug. The generated Code, also conforms the principle stated in the text. No SQL in Java. SQL is stored in individual resource file.
(another reason of not using CGLib is for the implementation simplicity)
lightor use Native SQL directly. The aim of lightor is not to hide the Relational DB. On the contrast, lightor aims to help programmers to understand better the relation database, SQL, JDBC. Lightor not conflicts with JDBC. They can be used together.
The first target of lightor is performance of query and processing of large amount data.
As I know, only lightor supports large amount data processing, since only lightor can accept ResultSet as parameter.
lightor provides more advanced cache policy compared to Hibernate, integrating query cache & ID Cache together so as to get better control. Lightor exposes API to programmer so as to control the cache intelligently.
5. SQL
HQL, OQL introduces OO features in to the SQL, pretending the underlying db is the ODB, instead of RDB.
I feel this is the Domain Pollution at grammar level, the pollution of OO to SQL, just like the feeing of LinQ which is the pollution of DB query to OO.
The use of Criteria API in Java is also the pollution of DB query to OO.
SQL is a widely used readable DSL.
In my view, the complete SQL should be put into an individual resource file, so that it can be copied to and run by the SQL client. Same principle applies to the specially optimized SQL.
HQL, OQL hinder the special optimization to SQL.
How to dynamically compose SQL? It is not an easy task.
Embedding SQL in Java. No. Better put SQL into an individual resource file.
Criteria API? No.
Using script logic in the SQL Template? For example, iBatis uses XML “if otherwise”; OR Bridge uses velocity.
It seems good. But still foreign logic in the SQL.
I have no good solution. I use fastm to handle it. Adding structure marker in the SQL. It is pollution too, since SQL is DSL, instead of structure description.
6. A Demo Forum
Farum is a simple forum demo, using fastm, lightor, lightweb, which is to show the principles described previously. https://farum.dev.java.net/files/documents/4372/25045/farum0.5a.zip
I feel that, the way to use a language should be making good uses of its features, instead of fixing those features as disadvantages.
The advantage of Java as a compile static typing language is the type checking at compilation time. How to make good use of this advantage? The Mapper Code generation described before, is a kind of try.
Other similar glue parts, as IoC, Validation etc, can also be tried this way. farum adopts this way. Manually written Validators do the job of validation, value setting, service implementation injection, etc.
Farum not uses Dynamic Proxy, CGLib which changes user code.
Avoid Reflection as much as possible, since Reflection escapes the type checking. If to use reflection, I would rather use the Dynamic Script Language.
Of course, reflection is difficult to avoid. farum uses a few of reflections too.
Thread Local is a kind of implicit contract, instead of explicit contract(method signature). Some usage of WebWork, the Open Session In View of Spring Framework, uses Thread Local.
farum not uses the Thread Local. It uses another way to implement Open Session In view. When the request hits the cache, it is no need to get connection from connection pool.
Summary
In another article <<Web Development Thoughts >>, I presented my ideal way of Web Development:
Quick development, fast runtime, elegant structure.
For each layer,
Web Layer should be Quick development.
O/R Layer should be fast runtime.
Template Layer should be elegant structure.
These are initial implementations of these thoughts.
Far from perfect, just to that direction.
Template Layer
fastm
https://fastm.dev.java.net/files/documents/1911/25042/fastm1.0c.zip
Web Layer
lightweb
https://lightweb.dev.java.net/files/documents/4371/25044/lightweb0.9b.zip
ORM Layer
lightor
https://lightor.dev.java.net/files/documents/4370/25043/lightor0.5a.zip
A forum demo using fastm + lightor + lightweb
farum
https://farum.dev.java.net/files/documents/4372/25045/farum0.5a.zip