Friday, November 09, 2007
Thursday, November 08, 2007
Math For Programmers - 程序员怎样学数学
Let me tell you about it.
自从我读了Johnny von Neumann的传记,我已经为弥补我糟糕的数学技能花了15个月了.读了大量的数学书籍,不过呢,似乎我还有更多没有读.当然我会接着做的.
现在我就来告诉你这些.
Conventional Wisdom Doesn't Add Up
这并不包括传统的智慧
First: programmers don't think they need to know math. I hear that so often; I hardly know anyone who disagrees. Even programmers who were math majors tell me they don't really use math all that much! They say it's better to know about design patterns, object-oriented methodologies, software tools, interface design, stuff like that.
首先:程序员不认为他们需要了解数学.我常常听到这样的话;我不知道还有会不同意这个的.甚至于以前是主修数学的程序员也告诉我他们真的不是常常使用到数学!他们说 更重要的是要去了解
And you know what? They're absolutely right. You can be a good, solid, professional programmer without knowing much math.
But hey, you don't really need to know how to program, either. Let's face it: there are a lot of professional programmers out there who realize they're not very good at it, and they still find ways to contribute.
但是呢,同时你也不是真的需要知道如何来编程.我们要面对的是:有很多专业的程序员,他们认识到他们不是非常擅长数学,但他们还是寻找方法去提升.
If you're suddenly feeling out of your depth, and everyone appears to be running circles around you, what are your options? Well, you might discover you're good at project management, or people management, or UI design, or technical writing, or system administration, any number of other important things that "programmers" aren't necessarily any good at. You'll start filling those niches (because there's always more work to do), and as soon as you find something you're good at, you'll probably migrate towards doing it full-time.
如果你突然觉得自己好烂,周围的人都远远的超过你,你会怎么想呢?好,你可能会发现自己善于项目管理,或者人事管理,或者界面设计,或技术写作,或者系统 管理,还有许多其他程序员不必去精通的.你会开始堆积那些想法(因为工作永远干不完),当你发现一些你能掌握的东西时,你很可能会转移去全职的做这个工 作.
In fact, I don't think you need to know anything, as long as you can stay alive somehow.
So they're right: you don't need to know math, and you can get by for your entire life just fine without it.
实际上,我认为有些东西你不需要了解,当目前你还能够赖以生存.
所以他们是对的:你不需要了解数学,并且没有她你也能过的很好.
But a few things I've learned recently might surprise you:
- Math is a lot easier to pick up after you know how to program. In fact, if you're a halfway decent programmer, you'll find it's almost a snap.
- They teach math all wrong in school. Way, WAY wrong. If you teach yourself math the right way, you'll learn faster, remember it longer, and it'll be much more valuable to you as a programmer.
- Knowing even a little of the right kinds of math can enable you do write some pretty interesting programs that would otherwise be too hard. In other words, math is something you can pick up a little at a time, whenever you have free time.
- Nobody knows all of math, not even the best mathematicians. The field is constantly expanding, as people invent new formalisms to solve their own problems. And with any given math problem, just like in programming, there's more than one way to do it. You can pick the one you like best.
- Math is... ummm, please don't tell anyone I said this; I'll never get invited to another party as long as I live. But math, well... I'd better whisper this, so listen up: (it's actually kinda fun.)
但是最近我学到一些东西可能会让你也感到惊喜:
在你知道如何编程之后,数学更容易学会.实际上,如果你先学数学,然后半路出家做程序员的话,你会发现编程简直就是小菜一碟.
学校里教数学的方式都错了.仅仅是教学的方法错了,不是教数学本身错.如果你以正确 的方式学习数学的话,你会学的更快,记住这会更长,但对你作为一个程序员来说也更有价值.
哪怕了解一点点相关的数学知识就能让你写出可爱有趣的程序,否则会有些小难度.换 句话讲,数学是可以慢慢学的,只要你有时间.
没人能了解所有的数学,就是最棒的数学家也不是.数学领域正不断的扩展,当人们发明 新的形式去解决自己的问题时.一些给出的数学问题,也正如编程,不止一种方法可以去 解决他.你可以挑个你最喜欢的.
数学是......嗯,请别告诉别人我说过这个哈;当然我也不指望谁能邀请我参加这样的 派对,当我还活着的时候.但是,数学其实就是......我还是小声的说吧,听好了:(她其 实就是一种乐趣啦!)
你学到的数学(和你忘了的)
Here's the math I learned in school, as far as I can remember:
Grade School: Numbers, Counting, Arithmetic, Pre-Algebra ("story problems")
High School: Algebra, Geometry, Advanced Algebra, Trigonometry, Pre-Calculus (conics and limits)
College: Differential and Integral Calculus, Differential Equations, Linear Algebra, Probability and Statistics, Discrete Math
这儿是我能记得在学校学到的数学:
初中:数,数数,算术知识,初级代数("问题故事")
高中:代数,几何,高等代数,三角学,? (圆锥和极限)
大学:微积分,微分公式,线性代数,概率和统计,离散数学
How'd they come up with that particular list for high school, anyway? It's more or less the same courses in most U.S. high schools. I think it's very similar in other countries, too, except that their students have finished the list by the time they're nine years old. (Americans really kick butt at monster-truck competitions, though, so it's not a total loss.)
上面那个关于高中数学课程单子上所列的,怎么来着?美国高中几乎都是这样的课程设置.我认为其他国家也会很相似的,除了那些在9岁之前就掌握了这些课程的学生.(美国人同时却在热衷于玩魔鬼卡车竞赛,虽然如此,整个来说也算不上什么大损失.)
Algebra? Sure. No question. You need that. And a basic understanding of Cartesian geometry, too. Those are useful, and you can learn everything you need to know in a few months, give or take. But the rest of them? I think an introduction to the basics might be useful, but spending a whole semester or year on them seems ridiculous.
代数?是的.没问题.你需要代数.和一些理解解析几何的知识.那些很有用,并且在以后 几个月里,你能学到一切你想要的,十拿九稳的.剩下的呢?我认为一个基本的介绍可能 会有用,但是在这上面花整个学期或一年就显得很荒谬了.
I'm guessing the list was designed to prepare students for science and engineering professions. The math courses they teach in and high school don't help ready you for a career in programming, and the simple fact is that the number of programming jobs is rapidly outpacing the demand for all other engineering roles.
我现在意识到那个书单列表原是设计来准备给那些以后要当科学家和工程师的学生的.他们在高中里所教的数学课程并不是为你的编程生涯做准备的,简单的事实是多数的编程工作相比其他的工程师角色更加要求快速.
And even if you're planning on being a scientist or an engineer, I've found it's much easier to learn and appreciate geometry and trig after you understand what exactly math is — where it came from, where it's going, what it's for. No need to dive right into memorizing geometric proofs and trigonometric identities. But that's exactly what high schools have you do.
甚至于你打算当一名科学家或者一名工程师,我会发现这更加容易去学习和欣赏几何学和三角在你理解了什么是数学之后-- 数学它如何而来,如何而去,为何而生.不必去专研记住几何上的证明和三角恒等式.但是那确实是高中学校要求你必须去做的.So the list's no good anymore. Schools are teaching us the wrong math, and they're teaching it the wrong way. It's no wonder programmers think they don't need any math: most of the math we learned isn't helping us.
所以这样的书单列表不再有什么用了.学校教了我们不是最合适的数学,并且方式也不对.不奇怪程序员认为他们不再需要数学:我们学的大部分数学知识对我们的工作没什么大的帮助.
The Math They Didn't Teach You
他们没有教到你的那部分数学
The math computer scientists use regularly, in real life, has very little overlap with the list above. For one thing, most of the math you learn in grade school and high school is continuous: that is, math on the real numbers. For computer scientists, 95% or more of the interesting math is discrete: i.e., math on the integers.
在真实的生活中,计算机科学家有规则的使用数学,对于上面单子里列的有点小小超过. 举个例子,你在中学里学的大部分数学是连续性的:也就是说,数学是真实的数字.而对于计算机科学家来说,他们所感兴趣的部分是占95%也许更多的离散性的:比如,关于整数的数学.
I'm going to talk in a future blog about some key differences between computer science, software engineering, programming, hacking, and other oft-confused disciplines. I got the basic framework for these (upcoming) insights in no small part from Richard Gabriel's Patterns Of Software, so if you absolutely can't wait, go read that. It's a good book.
我打算在我以后blog中再谈一些在计算机科学,
For now, though, don't let the term "computer scientist" worry you. It sounds intimidating, but math isn't the exclusive purview of computer scientists; you can learn it all by yourself as a closet hacker, and be just as good (or better) at it than they are. Your background as a programmer will help keep you focused on the practical side of things.
到现在为止,不要让"计算机科学家"这个词困扰到你.它听上去很可怕,其实数学不是计算机科学家所独有的领域,你也能作为一个黑客自学它,并且能做的和他们一样棒.你作为一个程序的背景将会帮助你保持只关注那些有实践性的部分.The math we use for modeling computational problems is, by and large, math on discrete integers. This is a generalization. If you're with me on today's blog, you'll be studying a little more math from now on than you were planning to before today, and you'll discover places where the generalization isn't true. But by then, a short time from now, you'll be confident enough to ignore all this and teach yourself math the way you want to learn it.
数学,我们用来建立计算模型的,大体上是离散的整数.这是普遍化的做法.如果正好今天你在看这篇博客,从现在起你正了解到更多的数学,并且你会认识到那样的普遍化是不对的.更多的,你将有信心认为可以忽略所有这些,并以你想要的方式自学.
For programmers, the most useful branch of discrete math is probability theory. It's the first thing they should teach you after arithmetic, in grade school. What's probability theory, you ask? Why, it's counting. How many ways are there to make a Full House in poker? Or a Royal Flush? Whenever you think of a question that starts with "how many ways..." or "what are the odds...", it's a probability question. And as it happens (what are the odds?), it all just turns out to be "simple" counting. It starts with flipping a coin and goes from there. It's definitely the first thing they should teach you in grade school after you learn Basic Calculator Usage.
对程序员来说,最有效的离散数学的分支是概率理论.这是你在学校学完基本算术后的紧接着的课.你会问,什么是概率理论呢?你就数啊,看有多少次出现满堂 彩?或者有多次是同花顺. 不管你思考什么问题如果是以"多少种途径..."或"有多大几率的...",那就是离散问题.当他发生时,都转化成"简单"的计数.抛个硬币看看...? 毫无疑问在他们教你基本的计算用法后他们会教你概率理论.
I still have my discrete math textbook from college. It's a bit heavyweight for a third-grader (maybe), but it does cover a lot of the math we use in "everyday" computer science and computer engineering.
我还保存着大学里的离散数学课本.可能他只占了三分之一的课程,但是它却涵盖了我们几乎每天计算机编程工作大部分所使用到的数学.
Oddly enough, my professor didn't tell me what it was for. Or I didn't hear. Or something. So I didn't pay very close attention: just enough to pass the course and forget this hateful topic forever, because I didn't think it had anything to do with programming. That happened in quite a few of my comp sci courses in college, maybe as many as 25% of them. Poor me! I had to figure out what was important on my own, later, the hard way.
也真是够奇怪的,我的教授从没告诉我数学是用来干吗的.或者我也从来没有听说过.种种原因吧.所以我也从没有给以足够的注意:只是考试及格然后把他们都忘 光,因为我不认为她还和编程有啥关系.事情变化是我在大学学完一些计算机科学的课程之后,也许是25%的课程.可怜的人!我必须弄明白什么对于自己来说是 最重要的,然后再是向深度发展.
I think it would be nice if every math course spent a full week just introducing you to the subject, in the most fun way possible, so you know why the heck you're learning it. Heck, that's probably true for every course.
我想,如果每门数学课都花上整整一周的时间,而只是介绍让你如何入门的话,那将非常不错,这是最有意思的一种假设,那么你知道了你正学习的对象是哪种怪物了.怪物,大概对每一门课都合适.
Aside from probability and discrete math, there are a few other branches of mathematics that are potentially quite useful to programmers, and they usually don't teach them in school, unless you're a math minor. This list includes:
除了概率和离散数学外,还有不少其他的数学分支,可能对程序员相当的有用,学校通常不会教你的,除非你的辅修科目是数学.这些数目列表包括:
- Statistics, some of which is covered in my discrete math book, but it's really a discipline of its own. A pretty important one, too, but hopefully it needs no introduction.
- Algebra and Linear Algebra (i.e., matrices). They should teach Linear Algebra immediately after algebra. It's pretty easy, and it's amazingly useful in all sorts of domains, including machine learning.
- Mathematical Logic. I have a really cool totally unreadable book on the subject by Stephen Kleene, the inventor of the Kleene closure and, as far as I know, Kleenex. Don't read that one. I swear I've tried 20 times, and never made it past chapter 2. If anyone has a recommendation for a better introduction to this field, please post a comment. It's obviously important stuff, though.
- Information Theory and Kolmogorov Complexity. Weird, eh? I bet none of your high schools taught either of those. They're both pretty new. Information theory is (veeery roughly) about data compression, and Kolmogorov Complexity is (also roughly) about algorithmic complexity. I.e., how small you can you make it, how long will it take, how elegant can the program or data structure be, things like that. They're both fun, interesting and useful.
代数和线性代数(比如,矩阵).他们会在教完代数后立即教线性代数.这也简单,这但相当多的领域非常有用,包括机器学习.
数理逻辑.我有相当完整的关于这么学科的书没有读,是Stephen Kleene写的,Kleene closure 的发明者,我所知道的还有就是Kleenex.这个就不要读了.我发誓我已经尝试了不下20次,却从没有读完第二章.如果那位牛掰有什么更好的入门建议的 话可以给我推荐,给个回复.虽然,这明显是非常重要的一部分.
信息理论和柯尔莫戈洛夫复杂性理论.真不可思议,不是么?我敢打赌没哪个高中会教你其中任何一门课程.她们都是新兴的学科.信息理论是(相当相当相当相当 难懂)关于数据压缩,柯尔莫戈洛夫复杂性理论是(同样非常难懂)关于算法复杂度的.也就是说,你要把它压缩的尽量小,你所要花费的时间也就变的越长,同样 的,程序或数据结构要变得多优雅也有同样的代价.他们都很有趣,也很有用.
...
For More ...
全文在这...
Tuesday, November 06, 2007
iPhone - 谁为iPhone创造了价值
iPod和iPhone,都是由遍布多国的数十家公司分工制造而成,每一生产阶段都为最后的价值做出大小不一的贡献。三位Irvine加州大学的研究员在斯隆基金会的资助下完成了一项针对美国市场上一款零售价为299美元30GB的iPod供应链的研究。
三位教授的研究发现,iPod真正的价值不在于内含的零件,更不在于把零件组装起来的整合机,而是集中在iPod的构思与设计。苹果聪明在想出如何把451种普通零件,组装成一台高价值的产品。苹果未必亲手制造iPod,但他们是其创造者。这才是关键。
据报告的粗略分析,苹果借品牌和设计当仁不让地拿到了大头80美元;75美元分给美国的渠道商与零售 商;13美元由林林总总的美国国内零组件厂商瓜分;由东芝制造的最昂贵的硬盘,成本价约73美元;最末阶段的组装在中国大陆完成,每台约4美元。其余还有 54美元的构成说不清楚,韩国的三星该有不少进账。
组装生产的特殊性值得一提。留给中国的虽然只有4美元收入(要覆盖组装生产、库存、厂房租金、运输、水电、工资等所有工厂开支),每一台iPod成品出口到美国,却要记入中国出口额150美元。这是目前美中贸易逆差巨大的重要原因之一。
iPhone同样是一个庞大的敏捷供应链生产。此前业内估计,iPhone带给苹果的利润率在20%至 50%之间,而根据分析公司iSuppli进行的拆卸确定,8GB iPhone的硬件物料清单和制造成本共为265.83美元,按照每个8GB iPhone以599.00美元的零售价进行出售,那么它的毛利润率超过了55%。当然,该估算成本中未包括专利权费、物流、销售等费用。
iSuppli的拆卸分析认为,在各部件供货商中,三星公司仍为最大的获利者。在8GB版iPhone 的成本里,三星公司提供的部件总计占了76.25美元,占BOM(物料清单)的30.5%,是最大的供货商;触摸屏模块的提供商为德国Balda参股的坐 落在中国的TPK制造厂,该模块估算成本为27美元,占8GB版iPhone BOM的10.8%;显示屏则来自包括EPSON、SHARP、Toshiba Matsushita等多家厂商,预估成本为24.5美元,占8GB版iPhone BOM的9.8%;德国的英飞凌是苹果家族供应商的新成员,为iPhone提供了包括数字基带、无线发射和电源管理等核心通信部件,预估总成本为 15.25美元,占8GB版iPhone BOM的6.1%;美国国家半导体公司提供的元件在BOM单中占的比例较小,仅为1.5美元,不到1%;iPhone由鸿海旗下的富士康负责组装。
Monday, October 29, 2007
Object Oriented ASP: Using Classes in Classic ASP
**************cBook.asp********************
< %
Class cBook
'Private, class member variable
Private m_ID
'Read the current ID value
Public Property Get ID()
ID = clng(m_ID)
End Property
'store a new ISBN value
Public Property Let ID(p_Data)
m_ID = p_Data
End Property
'############# Public Functions, accessible to the web pages ##############
'Loads this object's values by loading a record based on the given ID
Public Function LoadFromId(p_Id)
dim strSQL, MyID
MyID = clng(p_Id)
strSQL = "SELECT * FROM Book WHERE (lngBookID = " & MyID & ") "
LoadFromId = LoadData (strSQL)
End Function
Private Function LoadData(p_strSQL)
dim rs
set rs = LoadRSFromDB(p_strSQL)
LoadData = FillFromRS(rs)
rs. close
set rs = nothing
End Function
'Takes a recordset
'Fills the object's properties using the recordset
Private Function FillFromRS(p_RS)
select case p_RS.recordcount
case 1
Me.ID = p_RS.fields("lngBookID").Value
case -1, 0
'err.raise 2, "Item was not found"
case else
err.raise 3, "Item was not unique"
end select
End Function
public Function Save()
Dim strSQL
'If the book has an existing (Autogenerated!) ID, then run an insert
if Me.ID < 1 then
Me.ID = InsertRecord("Book", "lngBookID", ...)
'Otherwise run an update
else
strSQL = strSQL & " UPDATE Book SET ... where lngBookID = " & Me.ID
RunSQL strSQL
End if
Save= Me.ID
End Function
End Class
% >
**************cBooks.asp********************
Class cBooks
'Private, class member variable
Private m_Books
Sub Class_Initialize()
set m_Books = Server.CreateObject ("Scripting.Dictionary")
End Sub
Sub Class_Terminate()
set m_Books = Nothing
End Sub
'Loads all books into the library
Public Function GetAllBooks()
dim strSQL
strSQL = "SELECT * FROM Book "
GetAllBooks = LoadBookData (strSQL)
End Function
Private Function LoadBookData(p_strSQL)
dim rs
set rs = LoadRSFromDB(p_strSQL)
FillBooksFromRS(rs)
LoadBookData = rs.recordcount
rs. close
set rs = nothing
End Function
'Takes a recordset
'Fills the object's properties using the recordset
Private Function FillBooksFromRS(p_RS)
dim myBook
do while not p_RS.eof
set myBook = New cBook
myBook .ID = p_RS.fields("lngBookID").Value
myBook .Title = p_RS.fields("strTitle").Value
m_Books.Add myBook.ID, myBook
p_RS.movenext
loop
End Function
End Class
**************default.asp********************
Dim myBook
Set myBook = New cBook
myBook.ID = ...
**************edit_book.asp********************
Dim myBook
Set myBook = new cBook
myBook.loadById(request("bookid"))
myBook.Title = Request.Form("title")
myBook.Save
Friday, October 26, 2007
Oracle PL/SQL
Login to SQL*Plus:
sqlplus username/password
Finding the objects in the database:
select owner, object_name , object_type from dba_objects where object_name like 'cust%';
Finding the structure of a table:
desc customers;
Creating Tables in Default tablespace:
create table customers
(
CUST_ID NUMBER(5) NOT NULL,
CUST_NAME VARCHAR2(20) NOT NULL,
CUST_DATE Date NULL
);
DUAL table: A standard Oracle database table named DUAL, which contains exactly one row.
select abs(-1) from dual;
Using Sequences:
create sequence student_id start with 1 increment by 1 cache 20 order;
select student_id.nextval from dual;
to see the contents of the database sequence
desc user_sequences;
select * from user_sequences;
To find out what default tablespace is assigned when our Oracle account was initially created:
select * from user_users;
Storage Characteristics of Tables
select * from user_tablespaces;
To_Date Function:converts a string to a date
to_date( string1, [ format_mask ], [ nls_language ] )
to_date('2003/07/09', 'yyyy/mm/dd')
Tuesday, June 26, 2007
ViewState and Page Life Cycle
The ASP.NET Page Life Cycle
About ViewState:
1. Server Controls utilize ViewState as the backing store for most, if not all their properties.
2. TrackViewState will turn tracking ON, and ONLY when tracking is ON, any changes to any of the StateBag's values will cause that item to be marked as "Dirty".
3. TrackViewState was call during the OnInit phase of the page/control lifecycle.
4. When the StateBag is asked to save and return it's state (StateBag.SaveViewState()), it only does so for the items contained within it that are marked as Dirty.
5. In the case of ViewState backing, setting the property to NULL will result in resetting the property back to it's default value.
WHAT DOESN'T VIEWSTATE DO?
- Remember any state information across page loads (only postbacks) (that is unless you customize how the data is persisted)
- Remove the need to repopulate data on every request
- ViewState is not responsible for the population of values that are posted such as by TextBox controls (although it does play an important role)
Page life cycle:
- Initialization
- LoadViewState (occurs only on PostBack)
- LoadPostDackData (occurs only on PostBack)
- Load
- RaisePostBacKEvent (occurs only on PostBack)
- SaveViewState
- Render
Page events still fire during partial postbacks
Use IsPostBack and IsInAsyncPostBack to avoid accidental execution of Page_Load code during partial postbacks
In conjunction with __doPostBack, __EVENTTARGET may be used to limit UpdatePanel life cycle event execution to only the targeted panel
UpdatePanel events fire on each and every request
if (Request["__EVENTTARGET"] == UpdatePanel1.ClientID)
{
// Insert magic here.
}
Control events are raised after Load events
By using PreRender instead of Load, you can allow control events to be handled before your code executes
Wednesday, June 06, 2007
.Net Framework 3.0 Introduce
相信大家对.Net Framework 3.0已经不再陌生了吧,具体的内容不用我介绍。我只是通过下面的一张图来对.Net Framework 3.0进行一个非常简单的介绍。
从图上我们可以看到3.0是以.Net Framework 2.0为核心,分别对不同技术和应用层面提供的一些模块。我记得一篇文章里面说到.Net Framework 3.0 不应该叫3.0更确切的叫.Net Framework 2.5(哈哈!不知道大家是否赞同这个说法)。
在.Net Framework 3.0包含了四个模块:
WPF(Windows Presentation Foundation):
WPF is a productive, unified approach to UI, Media, and Documents that you can use to deliver unmatched user experiences to your customers.
WPF提供了一个统一UI、媒体和文档的用户体验。
WPF统一了WinForm和Web的用户体验开发。
WCF(Windows Communication Foundation):
Unified framework for rapidly building service-oriented applications
WCF是一个迅速的建立SOA应用的框架。
WCF集成了WebService、Remotting和Com+的一些特征。
WF(Windows Workflow Foundation):
The Programming Model, Engine And Tools For Building Workflow Enabled Applications On Windows Platform.
在Windows平台上提供一个构建工作流程应用的模块、引擎和工具。
CardSpace(Windwos CardSpace):
Technology that simplifies and improves the safety of online login and authentication.
CardSpace是一个提供统一安全管理和身份认证的技术
Tuesday, June 05, 2007
UML Tools & Data Model Tools
ENTERPRISE ARCHITECT
Rational Rose
Visual Paradigam
MagicDraw UML
UModel
VSTS
XDE
Visio
Data Modeling
Toad Data modeler
PowerDesign
ERWin
ER Studio
Case Studio
Tuesday, May 22, 2007
MSMQ
System.Messaging
Type
Public : publish on ActiveDirectory , ServerName\QueueName
Private : on local only , .\Private$\MyNewQueue ; FormatName:DIRECT=OS:machinename\private$\queuename
Class
Message
MessageQueue
Monday, April 30, 2007
SCRUM, XP and TDD - Agile Software Development
1) Coordination
C: The work item belongs to all members, but not only one. Every one should be enthusiastic on working out all work items in a sprint however some of them are not assigned to him at beginning. They have only one final goal, delivering the project on time efficiently and high quality.
2) Positivity
C: That's why in MS, PMs, developers and testers are in the same level. All members should participate the project actively. The team should be responsible for the project but not the PM only. One failed all failed!
In China, there are already some teams using Agile even XP now. Surely, scrum also seems strange to them. Have you agreed that in China, from developing technologies (application level) speaking, we're not weeker than US/UK guys. But projecting is normally 5~10 years behindhand. Most developers, PMs, and even company owners pay less attention on PROJECTING.
The developers mostly care on how to make the code beautifully and clearly. The PMs mostly care on delivering project on time. The CEOs mostly care on getting the money from customers faster. They're not wrong, but they're short eyes. They're producing software, it bases on human but not machine. It doesn't base on only one guy, but a group. So the first thing is HOW TO BUILD THE TEAM! WHAT'S THE PROCESS FOR TEAM RUNNING.
The BUILDING AND PROCESS is not the silver bullet for a employee of a company. But it should be caused by the high level managers. Frankly, most chairmen in China is not expert on software, but have a perfect relationship to sell them whatever they are!
Wednesday, April 18, 2007
NDoc 1.3, NDoc 2005 and Sandcastle
NDoc 1.3 stop development at 2005 and is only working for .Net framework 1.0 and 1.1, can only import solution from VS 2003.
By adding a config file and recompile in VS 2005 it will work with .Net 2.0, but the generic class name will show improperly. This can be fixed by add FullName test function.
NDoc 2005 seems to take this projects and develop on .Net 2.0.
Microsoft has their own documentation tool Sandcastle.
One more thing, today I found a very good HTTP debugging tool: Fiddler. It logs all HTTP traffic between your computer and the Internet.
Monday, April 16, 2007
Custom List Class in c#
/// Collection of users.
/// </summary>
[Serializable()]
public class Users : ArrayList
{
#region Public Properties
/// <summary>
/// Returns a specific user.
/// </summary>
public new User this[int index]
{
get
{
return ((User)base[index]);
}
}
#endregion
#region Public Methods
/// <summary>
/// Add a user to the collection
/// </summary>
/// <param name="user">The user to be added.</param>
/// <returns>Index of the added user.</returns>
public int Add(User user)
{
return base.Add(user);
}
/// <summary>
/// Object version of the typed 'Add' method.
/// Do not use.
/// </summary>
/// <param name="value">Ignored.</param>
/// <returns>Always throws an exception</returns>
public override int Add(object value)
{
throw new Exception("Please call the typed overload");
}
/// <summary>
/// Insert the user at a given index.
/// </summary>
/// <param name="index">Index location to insert the user.</param>
/// <param name="user">The user to be added.</param>
public void Insert(int index, User user)
{
base.Insert(index, user);
}
/// <summary>
/// Object version (weak typed) of the 'Insert' method.
/// Do not use.
/// Exception will be thrown always.
/// </summary>
/// <param name="index">Ignored</param>
/// <param name="value">Ignored</param>
public override void Insert(int index, object value)
{
throw new Exception("Please call the typed overload (Insert(int, User))");
}
/// <summary>
/// Remove a user from the documemt.
/// </summary>
/// <param name="user">Reference of the user to remove.</param>
public void Remove(User user)
{
base.Remove(user);
}
/// <summary>
/// Check if the collection contains the user specified.
/// </summary>
/// <param name="user">The user to look for in the collection.</param>
/// <returns>True/False if the user exists in the list.</returns>
public bool Contains(User user)
{
return base.Contains(user);
}
#endregion
}
Thursday, April 12, 2007
Wednesday, April 11, 2007
VS 2003 can't load Web projects and AssemblyKeyFile setting
After I delete VS 2003 web cache file from the following folder, the web projects get loaded.
C:\Documents and Settings\cguo\VSWebCache
Some other dll projecys has compile error:
error CS1548: Cryptographic failure while signing assembly '...' -- 'Error reading key file '...' -- The system cannot find the file specified.
The setting in AssemblyInfo.cs has one KeyFile setting, the file is using related path to solution, after I change to related path to project file, the error gone.
Thursday, March 15, 2007
Castle + iBatisNet + ASP.Net & MonoRail
Make sure each property has a set/get for the class used as ResultMap
2. Manager use iBatisNet DataMapper
Add reference:
IBatisNet.Common
IBatisNet.DataMapper
3. Business implement automatic transaction
Add reference:
Castle.Services.Transaction
Castle.Facilities.IBatisNetIntegration
Castle.Facilities.AutomaticTransactionManagement
[Transactional]
[UsesAutomaticSessionCreation]
public partial class ProductsBusinessRules : BusinessRulesBase, IProductsBusinessRules
{
...
[Transaction(TransactionMode.Requires)]
public void Save(SearchableSortableBindingList
{
...
}
}
4. NUnit
Add reference:
Castle.Core
Castle.Windsor
Castle.MicroKernel
Castle.Services.Transaction
Castle.Facilities.IBatisNetIntegration
Castle.Facilities.AutomaticTransactionManagement
NUnit.Framework
//AbstractBusinessRulesTestCase.cs
public class AbstractBusinessRulesTestCase
{
protected IWindsorContainer container;
public AbstractBusinessRulesTestCase()
{
}
[TestFixtureSetUp]
public void Init()
{
container = new WindsorContainer("configuration.xml");
}
[TestFixtureTearDown]
public void Terminate()
{
container.Dispose();
}
}
//
public class ProductsBusinessRulesTestCase : AbstractBusinessRulesTestCase
{
[Test]
public void RetriveAll()
{
IProductsBusinessRules bizRule = container.Resolve
SearchableSortableBindingList
}
}
Project properies setting:
Start external program: nunit-gui.exe
Command line argument: test dll file name
Copy all config file to Debug\Bin folder:
configuration.xml: the replace file for web.config
components.config: components setting for Castle
facilities.config: facilities
providers.config: providers for iBatisNet DataMapper
SqlMap.config: SqlMap for iBatisNet DataMapper
//
<configuration>
<include uri="file://facilities.config"/>
<include uri="file://components.config"/>
</configuration>
Change SqlMap setting in SqlMap.config accordingly.
5. MonoRail
New "Castle MonoRail Projects"
New ProductsController under Controllers folder
//ProductsController.cs
[Layout("default"), Rescue("generalerror")]
public class ProductsController : SmartDispatcherController
{
private IProductsBusinessRules productBizRules;
public ProductsController(IProductsBusinessRules productBizRules)
{
this.productBizRules = productBizRules;
}
public void Index()
{
PropertyBag["products"] = productBizRules.RetrieveAll();
}
}
New view file under Views folder
//Index.rails, under /Views/Products
#foreach($item in $products)
$item.ProductName
#end
Browse to
http://localhost/shop/products/index.rails
Wednesday, March 07, 2007
Problem with Moneris Credit Payment Gayway
One of our online store client use Moneris merchant account. So we decide integrate Moneris with out credit card payment API. After doing some testing, we found some interesting thing:
1. Moneris required unique order id to be provided in each transaction, include Sale, PreAuth, PostAuth, Credit or Void. In PostAuth and Void case, it also need transaction id.
In some other payment gateway like Verisign, it doesn't need any id in Sale and PreAuth, and ask Reference id only in PostAuth and Void.
2. The amount must contain 3 digits with two penny values.
At our test, the total amount is $12 in shopping card, and comes an error "Incorrect amount parameter:12".
At the beginning I think is doesn't accept integer, which is impossible.
Then I hard code this value(12) in the Moneris eSELECTplus COM object, I found out it's true that the COM object doesn't like integer. But if it's 12.00, it go through.
So the problem is the total amount in pages showing 12.00, and after passing to some function call, when it gets to Moneris, it was so how change to 12. Eventually it's the function "CDbl".
As I found out those two penny values is important. I just format the amount again to keep those and then past it to Moneris. Then everything working great.
But when we direct give a 12.0
Monday, March 05, 2007
Thursday, March 01, 2007
Reguler Expression 正则表达式
\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个后向引用、或一个八进制转义符。
^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的Multiline 属性,^ 也匹配 ’\n’ 或 ’\r’ 之后的位置。
$ 匹配输入字符串的结束位置。如果设置了 RegExp 对象的Multiline 属性,$ 也匹配 ’\n’ 或 ’\r’ 之前的位置。
* 匹配前面的子表达式零次或多次。
+ 匹配前面的子表达式一次或多次。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。? 等价于 {0,1}。
{n} n 是一个非负整数,匹配确定的n 次。
{n,} n 是一个非负整数,至少匹配n 次。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。在逗号和两个数之间不能有空格。 ? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。
. 匹配除 "\n" 之外的任何单个字符。要匹配包括 ’\n’ 在内的任何字符,请使用象 ’[.\n]’ 的模式。
(pattern) 匹配pattern 并获取这一匹配。
(?:pattern) 匹配pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。
(?=pattern) 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。
(?!pattern) 负向预查,与(?=pattern)作用相反
x|y 匹配 x 或 y。
[xyz] 字符集合。
[^xyz] 负值字符集合。
[a-z] 字符范围,匹配指定范围内的任意字符。
[^a-z] 负值字符范围,匹配任何不在指定范围内的任意字符。
\b 匹配一个单词边界,也就是指单词和空格间的位置。
\B 匹配非单词边界。
\cx 匹配由x指明的控制字符。
\d 匹配一个数字字符。等价于 [0-9]。
\D 匹配一个非数字字符。等价于 [^0-9]。
\f 匹配一个换页符。等价于 \x0c 和 \cL。
\n 匹配一个换行符。等价于 \x0a 和 \cJ。
\r 匹配一个回车符。等价于 \x0d 和 \cM。
\s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。
\S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。
\t 匹配一个制表符。等价于 \x09 和 \cI。
\v 匹配一个垂直制表符。等价于 \x0b 和 \cK。
\w 匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]’。
\W 匹配任何非单词字符。等价于 ’[^A-Za-z0-9_]’。
\xn 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。
\num 匹配 num,其中num是一个正整数。对所获取的匹配的引用。
\n 标识一个八进制转义值或一个后向引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为后向引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。
\nm 标识一个八进制转义值或一个后向引用。如果 \nm 之前至少有is preceded by at least nm 个获取得子表达式,则 nm 为后向引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的后向引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。
\nml 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。
\un 匹配 n,其中 n 是一个用四个十六进制数字表示的Unicode字符。
"^\d+$" //非负整数(正整数 + 0)
"^[0-9]*[1-9][0-9]*$" //正整数
"^((-\d+)|(0+))$" //非正整数(负整数 + 0)
"^-[0-9]*[1-9][0-9]*$" //负整数
"^-?\d+$" //整数
"^\d+(\.\d+)?$" //非负浮点数(正浮点数 + 0)
"^(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*))$" //正浮点数
"^((-\d+(\.\d+)?)|(0+(\.0+)?))$" //非正浮点数(负浮点数 + 0)
"^(-(([0-9]+\.[0-9]*[1-9][0-9]*)|([0-9]*[1-9][0-9]*\.[0-9]+)|([0-9]*[1-9][0-9]*)))$" //负浮点数
"^(-?\d+)(\.\d+)?$" //浮点数
"^[A-Za-z]+$" //由26个英文字母组成的字符串
"^[A-Z]+$" //由26个英文字母的大写组成的字符串
"^[a-z]+$" //由26个英文字母的小写组成的字符串
"^[A-Za-z0-9]+$" //由数字和26个英文字母组成的字符串
"^\w+$" //由数字、26个英文字母或者下划线组成的字符串
"^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$" //email地址
"^[a-zA-z]+://(\w+(-\w+)*)(\.(\w+(-\w+)*))*(\?\S*)?$" //url
/^(d{2}|d{4})-((0([1-9]{1}))|(1[1|2]))-(([0-2]([1-9]{1}))|(3[0|1]))$/ // 年-月-日
/^((0([1-9]{1}))|(1[1|2]))/(([0-2]([1-9]{1}))|(3[0|1]))/(d{2}|d{4})$/ // 月/日/年
"^([w-.]+)@(([[0-9]{1,3}.[0-9]{1,3}.[0-9]{1,3}.)|(([w-]+.)+))([a-zA-Z]{2,4}|[0-9]{1,3})(]?)$" //Emil
"(d+-)?(d{4}-?d{7}|d{3}-?d{8}|^d{7,8})(-d+)?" //电话号码
"^(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5]).(d{1,2}|1dd|2[0-4]d|25[0-5])$" //IP地址
匹配中文字符的正则表达式: [\u4e00-\u9fa5]
匹配双字节字符(包括汉字在内):[^\x00-\xff]
匹配空行的正则表达式:\n[\s| ]*\r
匹配HTML标记的正则表达式:/<(.*)>.*<\/\1>|<(.*) \/>/
匹配首尾空格的正则表达式:(^\s*)|(\s*$)
匹配Email地址的正则表达式:\w+([-+.]\w+)*@\w+([-.]\w+)*\.\w+([-.]\w+)*
匹配网址URL的正则表达式:^[a-zA-z]+://(\\w+(-\\w+)*)(\\.(\\w+(-\\w+)*))*(\\?\\S*)?$
匹配帐号是否合法(字母开头,允许5-16字节,允许字母数字下划线):^[a-zA-Z][a-zA-Z0-9_]{4,15}$
匹配国内电话号码:(\d{3}-|\d{4}-)?(\d{8}|\d{7})?
匹配腾讯QQ号:^[1-9]*[1-9][0-9]*$
下表是元字符及其在正则表达式上下文中的行为的一个完整列表:
\ 将下一个字符标记为一个特殊字符、或一个原义字符、或一个后向引用、或一个八进制转义符。
^ 匹配输入字符串的开始位置。如果设置了 RegExp 对象的Multiline 属性,^ 也匹配 ’\n’ 或 ’\r’ 之后的位置。
$ 匹配输入字符串的结束位置。如果设置了 RegExp 对象的Multiline 属性,$ 也匹配 ’\n’ 或 ’\r’ 之前的位置。
* 匹配前面的子表达式零次或多次。
+ 匹配前面的子表达式一次或多次。+ 等价于 {1,}。
? 匹配前面的子表达式零次或一次。? 等价于 {0,1}。
{n} n 是一个非负整数,匹配确定的n 次。
{n,} n 是一个非负整数,至少匹配n 次。
{n,m} m 和 n 均为非负整数,其中n <= m。最少匹配 n 次且最多匹配 m 次。在逗号和两个数之间不能有空格。 ? 当该字符紧跟在任何一个其他限制符 (*, +, ?, {n}, {n,}, {n,m}) 后面时,匹配模式是非贪婪的。非贪婪模式尽可能少的匹配所搜索的字符串,而默认的贪婪模式则尽可能多的匹配所搜索的字符串。 . 匹配除 "\n" 之外的任何单个字符。要匹配包括 ’\n’ 在内的任何字符,请使用象 ’[.\n]’ 的模式。 (pattern) 匹配pattern 并获取这一匹配。 (?:pattern) 匹配pattern 但不获取匹配结果,也就是说这是一个非获取匹配,不进行存储供以后使用。 (?=pattern) 正向预查,在任何匹配 pattern 的字符串开始处匹配查找字符串。这是一个非获取匹配,也就是说,该匹配不需要获取供以后使用。 (?!pattern) 负向预查,与(?=pattern)作用相反 x|y 匹配 x 或 y。 [xyz] 字符集合。 [^xyz] 负值字符集合。 [a-z] 字符范围,匹配指定范围内的任意字符。 [^a-z] 负值字符范围,匹配任何不在指定范围内的任意字符。 \b 匹配一个单词边界,也就是指单词和空格间的位置。 \B 匹配非单词边界。 \cx 匹配由x指明的控制字符。 \d 匹配一个数字字符。等价于 [0-9]。 \D 匹配一个非数字字符。等价于 [^0-9]。 \f 匹配一个换页符。等价于 \x0c 和 \cL。 \n 匹配一个换行符。等价于 \x0a 和 \cJ。 \r 匹配一个回车符。等价于 \x0d 和 \cM。 \s 匹配任何空白字符,包括空格、制表符、换页符等等。等价于[ \f\n\r\t\v]。 \S 匹配任何非空白字符。等价于 [^ \f\n\r\t\v]。 \t 匹配一个制表符。等价于 \x09 和 \cI。 \v 匹配一个垂直制表符。等价于 \x0b 和 \cK。 \w 匹配包括下划线的任何单词字符。等价于’[A-Za-z0-9_]’。 \W 匹配任何非单词字符。等价于 ’[^A-Za-z0-9_]’。 \xn 匹配 n,其中 n 为十六进制转义值。十六进制转义值必须为确定的两个数字长。 \num 匹配 num,其中num是一个正整数。对所获取的匹配的引用。 \n 标识一个八进制转义值或一个后向引用。如果 \n 之前至少 n 个获取的子表达式,则 n 为后向引用。否则,如果 n 为八进制数字 (0-7),则 n 为一个八进制转义值。 \nm 标识一个八进制转义值或一个后向引用。如果 \nm 之前至少有is preceded by at least nm 个获取得子表达式,则 nm 为后向引用。如果 \nm 之前至少有 n 个获取,则 n 为一个后跟文字 m 的后向引用。如果前面的条件都不满足,若 n 和 m 均为八进制数字 (0-7),则 \nm 将匹配八进制转义值 nm。 \nml 如果 n 为八进制数字 (0-3),且 m 和 l 均为八进制数字 (0-7),则匹配八进制转义值 nml。 \un 匹配 n,其中 n 是一个用四个十六进制数字表示的Unicode字符。 匹配中文字符的正则表达式: [u4e00-u9fa5] 匹配双字节字符(包括汉字在内):[^x00-xff] 应用:计算字符串的长度(一个双字节字符长度计2,ASCII字符计1) String.prototype.len=function(){return this.replace([^x00-xff]/g,"aa").length;} 匹配空行的正则表达式:n[s| ]*r 匹配HTML标记的正则表达式:/<(.*)>.*|<(.*) />/
匹配首尾空格的正则表达式:(^s*)|(s*$)
应用:javascript中没有像vbscript那样的trim函数,我们就可以利用这个表达式来实现,如下:
String.prototype.trim = function()
{
return this.replace(/(^s*)|(s*$)/g, "");
}
利用正则表达式分解和转换IP地址:
下面是利用正则表达式匹配IP地址,并将IP地址转换成对应数值的Javascript程序:
function IP2V(ip)
{
re=/(d+).(d+).(d+).(d+)/g //匹配IP地址的正则表达式
if(re.test(ip))
{
return RegExp.$1*Math.pow(255,3))+RegExp.$2*Math.pow(255,2))+RegExp.$3*255+RegExp.$4*1
}
else
{
throw new Error("Not a valid IP address!")
}
}
不过上面的程序如果不用正则表达式,而直接用split函数来分解可能更简单,程序如下:
var ip="10.100.20.168"
ip=ip.split(".")
alert("IP值是:"+(ip[0]*255*255*255+ip[1]*255*255+ip[2]*255+ip[3]*1))
匹配Email地址的正则表达式:w+([-+.]w+)*@w+([-.]w+)*.w+([-.]w+)*
匹配网址URL的正则表达式:http://([w-]+.)+[w-]+(/[w- ./?%&=]*)?
利用正则表达式去除字串中重复的字符的算法程序:
var s="abacabefgeeii"
var s1=s.replace(/(.).*1/g,"$1")
var re=new RegExp("["+s1+"]","g")
var s2=s.replace(re,"")
alert(s1+s2) //结果为:abcefgi
我原来在CSDN上发贴寻求一个表达式来实现去除重复字符的方法,最终没有找到,这是我能想到的最简单的实现方法。思路是使用后向引用取出包括重复的字符,再以重复的字符建立第二个表达式,取到不重复的字符,两者串连。这个方法对于字符顺序有要求的字符串可能不适用。
得用正则表达式从URL地址中提取文件名的javascript程序,如下结果为page1
s="http://www.9499.net/page1.htm"
s=s.replace(/(.*/){0,}([^.]+).*/ig,"$2")
alert(s)
利用正则表达式限制网页表单里的文本框输入内容:
用 正则表达式限制只能输入中文:onkeyup="value="http://www.ygblog.com /value.replace(/["^u4E00-u9FA5]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^u4E00-u9FA5]/g,''))"
用正则表达式限制只能输入全角字符: onkeyup="value="http://www.ygblog.com/value.replace(/["^uFF00-uFFFF]/g,'')" onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^uFF00-uFFFF]/g,''))"
用正则表达式限制只能输入数字:onkeyup="value="http://www.ygblog.com /value.replace(/["^d]/g,'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,''))"
用正则表达式限制只能输入数字和英文:onkeyup="value="http://www.ygblog.com /value.replace(/[W]/g,"'') "onbeforepaste="clipboardData.setData('text',clipboardData.getData('text').replace(/[^d]/g,''))"
UltraEdit中的正则表达式(Unix Style):
如果要加入下面黑体的部份到文本中
<Column name="BannersTitle" type="System.String" dbtype="NVarChar(8) NULL" UpdateCheck="Never" />
只要查找
<Column(.+)/>
替换成
<Column\1UpdateCheck="Never" />
同样要加入下面黑体的部份到文本中
[Column(Storage="_BannersTitle", DbType="NVarChar(8) NULL", UpdateCheck=UpdateCheck.Never)]
只要查找
\[Column(.+)\)\]
替换成
\[Column\1, UpdateCheck=UpdateCheck.Never\)\]
Friday, February 02, 2007
MonoRail - Web MVC model on ASP.NET
1. Download MonoRail from here.
2. If there's error "Project type not support" error while opening a MonoRail web project occur, download VS 2005 SP1 here.
3. Download a complete Castle Monorail sample project here.
4. In IIS, associate the extension you want to use (.rails) for MonoRail with ASP.Net ISAPI(aspnet_isapi.dll).
5. Deploying the application
To deploy, simply copy your webapp's bin and Views directory as well as Global.asax and your web.config files to /web/test and then you can point your browser at http://yourserver.com/test/index.rails.
Castle+iBatisNet+MonoRail
Castle+iBatisNet+Castle.MVC+ASP.NET
NVelocity engine
Change a library project to web project:
the simple way is open the .csproj in Notepad and change the line
<ProjectType>Local< /ProjectType>
to
<ProjectTypeGuids>{349c5851-65df-11da-9384-00065b846f21};{fae04ec0-301f-11d3-bf4b-00c04f79efbc}< /ProjectTypeGuids>
Some link:
Intro to MonoRail (cn)
Implement page cache for MonoRail (cn)
Use NDO in MonoRail (cn)
TerryLee's Castle Series
NDO
Castle ActiveRecord Issues
DotNet软件开发框架
基于Castle+IBatisNet+Castle.MVC的ASP.NET构架
使用IBatisNet + Castle 开发DotNet软件
IBatisNet+Castle构架开发指南 (续) 附代码生成模板
Asp.Net中获取Castle容器中的服务的另一方法
Thursday, February 01, 2007
Templates Based Web Application
First, I come to XOOPS. It is an extensible, OO (Object Oriented), easy to use dynamic web content management system written in PHP. It use Smarty engine, which take the template, parse it, and ouput .php file as result, some tags:
〈{if ...} >
〈{/if} >
〈{foreach ...>
〈{/foreach}>
Then, I found Shopify , which support customized layout and theme for each register store. In their admin pages, owner can change the liquid for template. Actually Shopify use Ruby on Rail and Mephisto Templates., some tags:
{% for ... in ... %}{% if ... %}
{% endif %}
{% endfor %}
In .Net platform, there are 4 template engine: Web Forms, NVelocity, Brail, StringTemplate. Here's comparisson. And MonoRail:View Engines Book also has some information.
In ASP.Net, we can loading user control as a ItemTemplate to accomplish similar work. This article give us a example to create templates dynamically in a DataList web server control like:
Repeater1.ItemTemplate = Page.LoadTemplate("usercontrol.ascx")
Using AJAX, the client can update certain part of the page. The data used to update the client can be a string, or even a rendered ouput of a user control, ScottGus Blog show us Cool UI Templating Technique to use with ASP.NET AJAX for non-UpdatePanel scenarios.
Alexander Kleshchevnikov, defined his email template tags and implement a parser in vb.net.
Wednesday, January 31, 2007
AJAX Framework: YUI, DOJO or GWT
White code in java, and then use GWT to compile to html and javascript file.
The Yahoo! User Interface (YUI) Library is a set of utilities and controls, written in JavaScript, for building richly interactive web applications using techniques such as DOM scripting, DHTML and AJAX. The YUI Library also includes several core CSS resources.
Dojo - is an Open Source DHTML toolkit written in JavaScript. It builds on several contributed code bases (nWidgets, Burstlib, f(m)), which is why we refer to it sometimes as a "unified" toolkit. Dojo aims to solve some long-standing historical problems with DHTML which prevented mass adoption of dynamic web application development.
One book for Dojo.
MochiKit - A lightweight Javascript library.
MooTools is a compact, modular, Object-Oriented JavaScript framework designed for the intermediate to advanced JavaScript developer. It allows you to write powerful, flexible, and cross-browser code with its elegant, well documented, and coherent API.
Prototype is a JavaScript Framework that aims to ease development of dynamic web applications.
Developer Notes for prototype.js
Tuesday, January 23, 2007
Format DateTime in XSLT in .Net 2.0
XmlDocument xmlDoc = new XmlDocument();
xmlDoc.LoadXml(xmlstring);
XslCompiledTransform xslDoc = new XslCompiledTransform(true);
StringReader strReader = new StringReader(xslstring);
XmlTextReader txtReader = new XmlTextReader(strReader);
xslDoc.Load(txtReader);
StringWriter strWriter = new StringWriter();
xslDoc.Transform(xmlDoc, null, strWriter);
outputstring = strWriter.ToString();
It's easy and simple to call this functions. But it takes time to write a working style sheet. One difficult thing is do datetime formating.
format-number is include in XSLT 1.0 , but not format-date. Each company have their extension to do that. For microsoft, this is the way doing it:
〈?xml version="1.0" encoding="UTF-8"?>
〈xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform" xmlns:ms="urn:schemas-microsoft-com:xslt" xmlns:dt="urn:schemas-microsoft-com:datatypes">
〈xsl:template match="/DocumentElement">
〈table border="1">
〈tr bgcolor="grey">
〈th>BaseCurrExch〈/th>
〈th>OrdDate〈/th>
〈/tr>
〈xsl:for-each select="Row">
〈tr bgcolor="white">
〈td>〈xsl:value-of select="format-number(BaseCurrExch,'#.00')"/>〈/td>
〈td>〈xsl:value-of select="ms:format-date(OrdDate, 'MM/dd/yyyy')"/>〈/td>
〈/tr>
〈/xsl:for-each>
〈/table>
〈/xsl:template>
〈/xsl:stylesheet>
For more information, check Microsoft XPath Extension Functions.
Wednesday, January 17, 2007
MyGeneration and O/R Mapping Practics
Some template in MyGeneration can generate data access code according the key and index define on data fields. This will save your time to create your own code manually. We use to have these fields:
PKID (int,4) Indentity
DateCreated(datetime, 8)
LastUpdate(datetime, 8)
rowguid(uniqueidentifier, 16): (newid())
Tuesday, January 16, 2007
Use SmtpClient to Send Email
MailAddress from = new MailAddress(emailfrom);
MailAddress to = new MailAddress(emailto);
MailMessage mm = new MailMessage(from, to);
mm.Subject = subject;
mm.Body = body;
mm.IsBodyHtml = true;
mm.Attachments.Add(New Attachment(AttachmentFile.PostedFile.InputStream, AttachmentFile.FileName))
SmtpClient sc = new SmtpClient();
sc.DeliveryMethod = SmtpDeliveryMethod.Network; // Network;PickupDirectoryFromIis; SpecifiedPickupDirectory
sc.Host = host;
sc.Port = Convert.ToInt32(port)
sc.Credentials = New NetworkCredential(username, password);
sc.Send(mm);
Here AttachmentFile is a FileUpload control inside the page:
<asp:FileUpload ID="AttachmentFile" runat="server" />
If we do not want to specify the Host information, we can config it inweb.config, and SmtpClient will use this setting to connect to SMTP server:
<configuration>
<system.net>
<mailSettings>
<smtp>
<network host="relayServerHostname" port="portNumber" userName="username" password="password" />
</smtp>
</mailSettings>
</system.net>
<system.web> ... </system.web>
</configuration>
SmtpClient throws SmtpException exception.
Friday, January 12, 2007
Use WebSupergoo ABCPdf.Net component
For example, we want all content inside the Literal control "litReport" to output to PDF, first we render the Literal web control to a string writer, then use AddImageHtml method of ABCPdf to load the content.
using System.Text;
using System.IO;
using WebSupergoo.ABCpdf5;
......
StringWriter sw = new StringWriter();
HtmlTextWriter htw = new HtmlTextWriter(sw);
litReport.RenderControl(htw);
Doc theDoc = new Doc();
theDoc.Color.Color = System.Drawing.Color.White;
theDoc.Rect.Inset(20,20);
int theID = 0;
theDoc.FrameRect();
theID = theDoc.AddImageHtml(sw.ToString());
while (true)
{
theDoc.FrameRect(); // add a black border
if (!theDoc.Chainable(theID))
break;
theDoc.Page = theDoc.AddPage();
theID = theDoc.AddImageToChain(theID);
}
After this, we use GetData to get the raw data and use BinaryWrite to output to browser.
Response.ContentType = "application/pdf;";
Response.AppendHeader("content-disposition", "attachment; filename=\"file.pdf\"");
Response.BinaryWrite(theDoc.GetData());
Response.Flush();
Response.End();
Monday, January 01, 2007
How to setup SVN on windows
Subversion Find server side component, svn-1.4.2-setup.exe is for windows setup.
Svn service Run svn server (svnserve.exe) as MS Windows service (Don't need since SVN v1.4)
TortoiseSVN Client side component
2. Install and setup SVN server
Run setup file. Then Create a repository and configure access:
Create a new directory like d:\subversion\repositories, open a command line window and go inside this folder, run
svnadmin create "d:\subversion\repositories"
This will create repository stucture folder under d:\subversion\repositories, go to d:\subversion\repositories\conf, change file svnserve.conf, uncomment the following line:
[general]
password-db = passwd
change file passwd, uncomment the following line:
[users]
and add the username and password you want to use when connecting to your subversion server
3.Install svnservice, and run install.bat to install a service for SVN, then start service "Subversion Service"
Note:
From v1.4, svnserve can be run as a native Windows service. Use windows command line tools sc.exe to install svn service.
sc create svnservice
binpath= "c:\Subversion\bin\svnserve.exe --service -r D:\svnroot"
displayname= "SVNService"
depend= Tcpip
start= auto
where "svnservice" is any service name, and "D:\svnroot" is the repository, you can use --listen-port parameter as well.
Then you can use the following to start/stop svn service
net start svnservice
net stop svnservice
To delete svn service
sc delete svnservice
If the path to svnserve.exe contains spaces or other characters that
must be escaped, then you must enclose the path to svnserve.exe with
double-quotes, which themselves must be quoted using a backslash:
sc create svnservice
binpath= "\"c:\program files\subversion\bin\svnserve.exe\" ..."
4. In client side, install TortoiseSVN and reboot computer, then create one projects folder like d:\projects and right click this folder and click "Import" menu, use URL:
svn://ip/projects
The default port SVN used is 3690.