2004年08月31日

http://www.ootips.org/

2004年08月17日

阅读《Better, Faster, Lighter Programming in .NET and Java》http://www.onjava.com/pub/a/onjava/2004/07/14/BFLJava.html

感悟:
透明 除了domain(罗辑层)外,其他的都相对于domain是透明的,都是Servicees 包括persistent(数据层) presentation layer (表示层) 也就是说domain中不能够访问Services的方法,或者说domain不可以向Servic发消息——因为它不知道他们的存在

摘要:
In order to keep the business model light, simple, and easy to maintain, you want to keep it as uncluttered with ancillary code as possible. The services provided to the domain model should be transparent, meaning that you shouldn’t have to add anything to your domain objects to get the benefit of those services. At the very least, you shouldn’t have to add anything to them that you can’t safely ignore when you need to, such as at unit-test time.

This domain class doesn’t know anything about how it will be displayed to the user or how it will be persisted to the database. It is entirely focused on representing the code business abstraction invoice, and the rules that apply to its data. Nothing else clutters the code.

感悟:
数据层包含了对数据库所有操作,其他层如domain层必须通过数据层才可以来访问数据库。一切越过数据层直接操作数据库的操作都是不合法的。这样做所有的对当前特定的数据库操作都被封装到了这个数据层里了,对于其他层来说使用什么样的数据库已经变得透明起来。这样以后无论是对数据库的改动还是迁移到另外的数据库支持上,都是可以只在数据层来实现,无需对其他层的代码进行改动了。还有一点建立数据层不是只建立一个类表示数据层(当然这样可强制程序员必须按照层间协议做),我想多个类在一个命名空间里也可以,但这样如何约束程序员不能跨层操作呢?

object/relational (O/R)

 

摘要:
The persistence layer is the same way. By separating out your persistence logic into another class (PersistenceManager) you abstract away the common, non-business- specific functionality of interacting with a database to a transparent part of the code. To implement PersistenceManager, you have a variety of choices. You can implement the transactional script pattern, which is essentially what we did in the first page above. That is to say, you use the native data interaction objects provided by .NET (DataSet, SqlDataAdapter, etc.) to manually pull values out of the Invoice instance and modify the database, manually controlling any transactional semantics yourself.

On the other hand, you could use an object/relational (O/R) mapping framework to handle the work for you. O/R mappers are frameworks that, given a mapping file that relates class definitions with database schema, can auto-generate the SQL scripts needed to perform persistence activities. These kinds of frameworks simplify your code greatly by eliminating all of the hard-coded SQL scripts used by the transactional script pattern, and free you to work in terms of your domain model only. Currently, the major O/R mapping framework available to .NET developers is NHibernate, a .NET port of the popular Java Hibernate framework. NHibernate is an open source project found at nhibernate.sourceforge.net. Microsoft has its own O/R mapping technology called ObjectSpaces that is going to be released with Longhorn and/or Whidbey, but unless you are a beta tester for Microsoft, you can only get NHibernate at present.

摘要:
In the Java world, there are a hundred ways to do anything. If you want an MVC framework, there’s Struts, WebWork, SpringMVC, and one implementation for every J2EE vendor. For O/R mapping, there’s Hibernate, JDO, Kodo, EJBs, etc. Heck, there are even five or six viable IDEs. On the Microsoft side of the world, we have tended to be less diverse. We use Visual Studio for development, ADO.NET for data access, and ASP.NET for our web front end. There aren’t nineteen different web form strategies (Tapestry, Velocity, JavaServer Faces, etc.). However, that focus on a single vendor is starting to change.

If you take a look at SourceForge, you will notice that there are almost as many .NET projects as Java projects now. All of the major tools on the Java side are being ported to .NET. This list includes:

Struts.NET for web MVC
NHibernate for O/R mapping
NUnit for unit testing
Pico.NET and Spring.NET for lightweight alternatives to EnterpriseServices/COM+
NAnt for build management
CruiseControl.NET and Draco.NET for integration builds
C# support in Eclipse and IDEA

摘要:
In general, this means writing code that allows for the unknown. This sounds like an impossible proposition, but in reality, the key factor is understanding where future users are likely to want to change the way your application works, and making those areas as loosely coupled to the rest of the application as possible.

IDocument document = Document.CreateInstance(“some_document_type”,
    “some_assembly”);
The beauty of factory methods is that they can return any concrete type that implements IDocument, not just the original Document class, and they can look up the actual implementation at runtime using reflection. The implementation of CreateInstance might look like:

public static IDocument CreateInstance(string type, string asm)
{
    Assembly assembly = Assembly.Load(asm);
    return (Idocument)assembly.CreateInstance(type);
}

As long as the calling code has passed in an accessible assembly, and the type they asked for implements the IDocument interface, then it doesn’t matter what the concrete type is, or even if it existed when the application was first written.

A special note about reflection: it gets a bum rap. Reflection is slower than direct coupling, but usually measured at about two or three times slower. That means you shouldn’t do everything via reflection, but its judicious use for something like loading a dynamically assigned class at runtime (but binding it statically to a known interface) is perfectly reasonable, especially if you are talking about a modern distributed application, where the two more important criteria for boosting performance are limiting round trips on the network and minimizing hits to the database. If you can solve those problems, then maybe you can think about how a little reflection affects performance. I find that extensibility is usually a more important factor for me.

2004年08月16日

感悟

这几天看了些英文资料收获不小。

接口是抽象类更进一步的发挥,如果不考虑加入函数,首先应该考虑使用接口。

小知识点

switch后的条件必须是整型或字符串型

类中的this是只读的

判断一个类是什么类型 可以用is运算符 如Data is DataTable

在类构造函数中调用另一个被重载的构造函数,是不允许的吗?或者说在类的方法中不可以调用构造函数吗?

继续重构CSHARPOLEDB3

上次对那个统一接口的问题(IPassData)实现上,我被卡住了。现在想来,对特殊情况的了解是通往一般化的必经之路,因此先从一种情况的实现开始比较明智。

问题:我们考虑PassData的PassTable实现
在此之前,我想保留原有的实现方法,也就是说我想让EditBox dlg = new EditBox( this,reader , Table, false );中的reader也符合IPassData接口

考察下面传递PassData的函数接口
public EditBox( IWin32Window win, OleDbDataReader reader, string TableName, bool bInsert )
  {
   InitializeComponent();
   this.editBoxLogic = new EditBoxLogic();     
   this.editBoxLogic.LoadDataSource(reader,TableName,bInsert);
   dataGrid1.DataSource = this.editBoxLogic.GetDataSource(); 
  }
看来问题在EditBoxLogic类中,把它里面对reader的处理进行IPassData接口化。

下面的事情是:EditBox的OK按钮(更新数据按钮)

发现了个bug:当连续两次选中同一行点击Edit按钮就会提示出错。(类太多,思路很容易就混乱了)
下午利用Visio想把这个程序画成静态图,其中顺序图中的抽象类的Create()如何在图中表示呢?因为它不能是对象

先不不管那么多了(bug留着以后再处理)先处理我的通用接口

 

 

 

 

 

2004年08月12日

感悟

有时候我想发太理想 总是学些觉得我喜欢的东西 比如设计方面的东西 可是眼高手低 高深的看不懂 低的又做不来 而且有时候很尴尬 不知道做什么 所以我想要是有一天我真的做了程序员 恐怕没有这么多时间可以自由支配 还是得多编写程序才行 

我决定一天拿出一部分时间来 作些自己不喜欢但是很有实际的事情 写代码完成某些功能 然后不断的发现问题 利用晚上来思考解决他们 只有走走停停 做做想想才会更有收获

有种想法:

现在利用重构别人的代码来仔细的学习重构,再过两个月十月份开始着力开发ttly网,争取两个月开发出雏型。如果网站在2005年年初运行受到好评,则继续发展,否则2005年将不再续费空间和域名。

任务

继续重构那个CSHARPOLEDB3

问题:
现在的问题是列表界面form1和修改界面EditBox之间如何传递要修改的数据——是传递行还是传递dataTable?
a、传递行
优点:由于从列表界面到修改界面,实际上用户只是看到的(修改的)是一行。所以最直观的想法是传递行。
缺点:但是对于Winform程序来说,新的行对象是需要生成的,而对象DataTable是原先就有的,只不过在不同的界面间传递引用而已。
实现上的问题:
b、传递dataTable
优点:
缺点:
实现上的问题:
新想法:为什么不能两种方式都试验一下,看看最终结果再说。那得从实现思路开始考虑了,先从传递DataTable开始(目前认为更合理的)注意:要是两种方式都实现又不用写重复代码那么应该考虑好通用的接口。

研究同一种功能的多种实现是一种学习设计和学习功能实现相结合的折中办法。
这件事做值不值的,当发现一个问题需要有两个以上的未知问题要解,那么就该考虑把目标问题修正一下(分解现在的大问题为不同的小问题,把当前的目标定为其中的一个小问题)

下面的问题——如何设计实现两种实现形式的通用接口
1、如何用DataView.RowFilter显示选定的部分数据
private void MakeDataView()
{
   DataView dv = new DataView();

   dv.Table = DataSet1.Tables["Suppliers"];
   dv.AllowDelete = true;
   dv.AllowEdit = true;
   dv.AllowNew = true;
   dv.RowFilter = “City = ‘Berlin’”;
   dv.RowStateFilter = DataViewRowState.ModifiedCurrent;
   dv.Sort = “CompanyName DESC”;
  
   // Simple bind to a TextBox control
   Text1.DataBindings.Add(“Text”, dv, “CompanyName”);
}
2、通用接口IPassData

IPassData.GetSelectRowPrimaryKey()
IPassData.GetTable()

 

3、思路中断,理一下
            传过来的数据源  转化后的DataSource(用于显示)    直接获取用户选择数据行 转化后的所需的数据行 传回的数据
listView                   是一条条数据Add进去的              
  
DataGrid                   DataView(dataTable.DefaultView)

4、卡住了通用接口的实现—— 当感到比较疲惫就去休息一下 然后回来思考

using System;
using System.Data;

namespace CSHARPOLEDB3
{
 ///


 /// IPassData 的摘要说明。
 ///

 interface IPassData
 {
  int GetSelectRowPrimaryKey();
  DataTable GetTable();
 }

 public abstract class PassDataFactory
 {
  public static int PassTable = 0;
  public static int PassRow = 1;

  public static IPassData CreatePassData(int Type)
  {
   switch(Type)
   {
    case PassTable:
    {
     return new PassTable();
     break;
    }
    case PassRow:
    {
     return null;
     break;
    }
    default:
     throw new ArgumentException(“非法PassData类型!无法创建!”);
   }
  }

  
 }

 public class PassTable : DataTable,IPassData
 {
  public int GetSelectRowPrimaryKey()
  {
            return 0;
  }

  public DataTable GetTable()
  {
             return this;
  }
 }
}

以上代码编译没通过,提示Create()返回值要比IPassData访问性低。这里主要是interface 没有public造成的 修改语句interface IPassData 为public interface IPassData即可。同时switch语句中,Case后面需要一个常量,因此表示type的PassTable和PassRow应该定义为常量如public const int PassTable 否则通不过编译