2007年9月11日星期二

Event Broker Service

CAB中我们使用Event Broker Service来处理不同Module之间的通信。这样的目的是为了保持各个业务模块之间的松耦合。当CAB加载一个Module的时候,它会遍历该模块中所有标记为EventPublications的事件和标记为EventSubscriptions的方法,将他们放入事件容器中,所有的EventTopic的实例都会放在WorkItem.EventTopics集合中。

Publish an Event

在CAB中,我们可以通过在一个Event前面添加一个EventPublication属性来发布一个事件。该属性(Attribute)有两个参数,一个是事件名,另外一个是事件发布的范围。这里我们有三种发布方式:

  • PublicationScope.WorkItem,只对该WorkItem下有效
  • PublicationScope.Descendants,对该WorkItem有效,同时对它子的WorkItem也有效
  • PublicationScope.Global,对整个应用程序有效,对所有的WorkItem有效

下面的例子告诉我们如何发布一个全局有效的事件:

[EventPublication("event://UpdatesAvailable/New", PublicationScope.Global)]
public event SomeEventHandler UpdatesAvailable;

Subscribe an Event

同样,我们可以在一个方法前面添加EventSubscription属性来订阅一个事件(方法必须在事件发布范围之内)。不同的方法可以订阅同一个事件。在订阅事件的时候,我们可以指定该方法运行的线程规则,有三种可选的方案:

  • ThreadOption.Background,系统会创建一个独立的后台线程运行该方法。
  • ThreadOption.Publisher,该方法的执行和Publisher线程同步。
  • ThreadOption.UserInterface,在当前激活的界面线程中执行。该选项可以保证编辑数据同时没有更新的数据。

下面的例子说明如何订阅一个事件,并其和当前界面同一线程处理:

[EventSubscription("event://UpdatesAvailable/New", Thread=ThreadOption.UserInterface)]
public void NewUpdates(object sender, SomeEventArgs numUpdates)
{
       MessageBox.Show(numUpdates.ToString(), "Updates available");
}

Event Broker 的实现

在CAB中,Event Broker系统包含了下面几个类和接口:

  • EventTopic,定义一个在Publisher和Subscriber之间的事件主题
  • WorkItem,暴露一个EventTopics集合,它拥有一个注册EventTopic实例列表
  • EventInspector,检查所有的对象或组件,看是否存在事件发布和订阅(EventPublication或EventSubscription属性)。如果有,将publications和subscriptions注册到EventTopic中,同时将EventTopic添加到WorkItem.EventTopics集合中。

Command

当我们处理界面事件的时候,往往会遇到不同的界面元素处理同样的事件,比如:定义一个OpenFile菜单选项用来打开一个文件,同时定义在ToolBar上定义一个按钮来打开一个文件,这两个界面元素处理相同的业务。这时候,我们可以使用Command模式来处理此类设计。在CAB中,我们可以写一个事件处理方法,将该方法绑定到多个界面元素事件处理。

[CommandHandler(“TestButtonClick”)]
public void OnTestButtonClick(object sender, EventArgs e)
{
    MessageBox.Show("Successful");
}

上述代码定义了一个Command处理方法,CommandHandler属性(Attribute)“伴随一个Command名字”,用来申明该方法是用来处理名为TestButtonClick的命令。我们可以通过下列方法将一个Command绑定到一个UIElement事件:

WorkItem.Commands[Constants.CommandNames.TestButtonClick].AddInvoker(element1, "Click");
WorkItem.Commands[Constants.CommandNames.TestButtonClick].AddInvoker(element2, "Click");

其中参数element1或element2是我们想要绑定的UIElement,比如一个Button和MenuItem。我们可以看出不同的UIElement绑定到相同的事件处理方法。

参考:Command Patter http://www.cnblogs.com/zhenyulu/articles/69858.html

2007年9月10日星期一

Module & Component

一个CAB应用程序是由若干个Modules(DLLs)组成的。每个Module包含了很多的组件(Componet),这些组件既可以是可视化的也可以非可视化的组件,比方说SmartPart,Workspace,WorkItems,Services等等。

Component

CAB应用程序的最小单元是Component,它包含了下列类型的Component;

Visual Element

  • SmartParts
  • Items(Views 和 Controls)

Support for visual elements

  • WorkItems
  • Workspaces
  • UIExtensionSites

Non-visual elements

  • Commands
  • EventTopics
  • Services

Module

前面我们提到CAB应用程序是由Modules组成的,每个Module是一个独立的部署单元,CAB中提供一个在运行时加载Module的服务,在缺省情况下,该服务使用一个名为ProfileCatalog.xml文件来加载Modules。

当CAB加载一个模块的时候,它使用反射(Reflection)来判断该Module中是否包含一个实现IModule接口的类(通常情况下通过集成ModuleInit类来实现)。

我们可以使用SCSF来创建两种不同类型的Module:

  • Functional Module -- 只是给其它模块提供一些服务,并不实现一个Use-case,不包含一个WorkItem
  • Business Module -- 实现一系列相关的用例,包含WorkItems。
在CAB中,按Module来部署的这种设计可以让我们很容易的开发一个容易扩展的应用程序,每一个Module我们可以定义为一个Plugin,当一个成熟应用程序运行在客户现场的时候,我们可以很容易根据客户的需求开发一个独立的业务模块,而不会影响整个应用程序。各个业务模块之间的关系是松耦合的,我们可以通过EventPublisher和Subscribe模式来实现各个模块之间的相互操作或服务的调用。

WorkItem

WorkItem是一个运行时容器,该容器中包含完成一个用例所需要了各种各样的组件,组件可以是可视化的也可以是非可视化的,比如:SmartPart,Service,Commonds等等。

WorkItem中定义了如下的属性:

  • Services

Services是一个集合,用来管理所有和实现一个用例相关的Service,可以通过如下代码将一个Service添加到WorkItem中:

WorkItem.Services.AddNew<TestService, ITestService>();

上述的代码中,第一个参数是一个具体Service的实现,第二个参数是该Service的接口。

一旦将一个Service添加到WorkItem中,该WorkItem中的其它组件(比如SmartPart)可以使用如下代码获取该Service的一个引用。

ITestSerivce service = WorkItem.Services.Get<ITestService>();

  • SmartParts

同样,我们也可以向一个WorkItem中添加一个SmartPart:

TestView view = WorkItem.SmartParts.AddNew<TestView>("TestView");

我们也可以通过下面方法获取一个已经存在的SmartPart

TestView view = WorkItem.SmartPart.Get("TestView");

同时使用下面代码将一个SmartPart显示在Workspace中:

if(view == null )

{

     TestViewview=WorkItem.SmartParts.AddNew<TestView> ("TestView");

     WorkItem.Workspaces[WorkspaceNames.XXXXX].Show(view);

else

{

      WorkItem.Workspaces[WorkspaceNames.XXXXX].Activate(view);

}

在这段代码中,我们不难发现,当一个SmartPart已经存在的时候,我们不需要再添加一个实例到WorkItem中,这样可以保证对同一个SmartPart来说,只有一个实例在WorkItem中。

  • Workspaces

Workspaces的设计和上面SmartParts的设计一致,我们可以通过一个Workspace的唯一名字来获取对应的Workspace实例。

WorkItem.Workspaces[WorkspaceNames.XXXXX]

  • UIExtensionSites

同样,UIExtensionSites也是一个集合,用来管理UIExtensionSite,我们可以通过下列方法将一个UIExtensionSite添加到WorkItem中:

WorkItem.UIExtensionSites.RegisteSite(UIExtensionSiteNames.XXXX, XXXXXXX;

将一个UIExtensionSite添加WorkItem之后,我们可以用下列方法添加一个UIElement到UIExtensionSite中,比如在ToolBarStrip上添加一个Button:

WorkItem.UIExtensionSites[Constants.UIExtensionSiteNames.ButtonsBar].Add(new ToolStripButton());

  • Commands

Commands集合用来管理Command,

WorkItem.Commands[Constants.CommandNames.TestButtonClick].AddInvoker(element, "Click");

WorkItem中还定义了其它一些集合变量,比如Events,WorkItems和Items。这里我们就不一一详述。

 

WorkItem hierarchy

在CAB中,WorkItem具有一定的层次,最顶端的WorkItem是RootWorkItem,它在整个应用程序中是唯一的。RootWorkItem会在应用程序开始的时候加载,当我们使用SCSF创建一个业务模块的时候,它自动会创建一个WorkItem,并在该模块加载的时候,将该WorkItem添加到RootWorkItem中去。一个WorkItem中的组件可以访问同一WorkItem中的其它组件,同时也可以访问父WorkItem中的组件。基本的访问规则如下,一个组件可以访问下列组件:

  • 同一WorkItem中的
  • 父WorkItem中的
  • 祖父WorkItem中的(以此类推)

由此我们可以看出,RootWorkItem中的组件对于整个应用程序来说是共享的。我们可以activated and deactivated WorkItem。在同一时刻,只有一个WorkItem是处于激活状态。

从更高的层次上来说,一个WorkItem封装了一个Use-Case。WorkItem的层次性关系反映了业务中UseCases之间的关系。这样的一种关系可以帮助我们在设计阶段识别出相应的WorkItems。但是也并不是粒度越细越好,详细WorkItem设计参考其它文章。

2007年9月6日星期四

UI Elements

对于一些通用的界面元素,比如MenuItem,Toolbar,StatusBar等等,CAB有它统一的定义和实现。

在CAB中,将这些统一的界面元素定义为UIExtensionSite,每一个UIExtensionSite是用一个唯一名字标识的。开发人员(通常来说是Shell开发人员)将一个界面元素注册为一个UIExtensionSite,下面代码描述将一个MenuStrip注册为一个UIExtensionSite:

RootWorkItem.UIExtensionSites.RegisterSite(“FileMenu”, Shell.MainMenuStrip);

一旦注册成功后,模块开发人员就可以使用它添加相关的界面控件,比如下面代码将一个MenuItem添加到菜单栏中:

ToolStripMenuItem printItem = new ToolStripMenuItem("Print"); RootWorkItem.UIExtensionSites[“FileMenu”].Add(printItem);

注意:虽然开发人员可以直接使用RootWorkItem.UIExtensionSites["XXXX"]来获取相关的UIExtensionSite,并添加相应控件,但是一般来说这不是一个好的设计,Shell开发人员最好定义一组通用的Shell服务接口,在这些接口中实现如何添加控件到UIExtensionSite中,对于Module开发人员,他们只需要调用相关的接口去添加控件到UIExtensionSite中,这样,Module开发人员不需要关心Shell实现的具体细节。比如:AddButtonToToolBarStrip, AddMenuItemToMenuStrip,等等。

SmartPart & Workspce

SmartPart是一个应用程序的可视化组件,我们可以通过继承System.Windows.Forms.UserControl类来实现。一旦继承了UserControl类,开发人员就可以进行界面的设计。接下来我们需要将SmartPart显示在界面中(Workspace)。下面的代码描述了如何将SmartPart显示在指定的Workspace中:

TestView view = WorkItem.SmartParts.AddNew<TestView>(); 
WorkItem.Workspaces[“TestWorkSpace”].Show(view);

在上面的代码中,我们将TestView添加到WorkItem的SmartParts集合中,并且显示在名为“TestWorkSpace”的Workspace中。

Workspace是用来显示控件或SmartPart的组件,在CAB中包含了如下的Workspace类型:

  • WindowWorkspace.
  • MdiWorkspace.
  • TabWorkspace.
  • DeckWorkspace.
  • ZoneWorkspace.

2007年9月5日星期三

What's Great Software?

A great software should include two things. One is great software must satisfy the customer's requirements. Another one is great software must be well-designed, well-coded and easy to maintain, reuse and extend.

Two types people will think your software is great or not. One is customer, who will check if your software meet their requirements. Another is your co-workers. they will think your software is great when it is easy to maintain, reuse and extend.

2007年8月31日星期五

第五章 在模块中添加MVP模式兼容的视图

本文会涉及到如下内容:

  • 什么是MVP
  • 使用SCSF创建一个视图(View)
  • 设计视图(View)
  • 实现视图(View)逻辑
  • 在Shell中显示View
  • 实现Presenter逻辑
  • 如何实现ISmartPartInfoProvider

一、什么是MVP

当我们在写界面程序时,常常包含各种各样的界面控件,用户事件,事件响应的控制逻辑,如果将这些代码全部放在一个界面类中的话,该类会非常复杂,并且很难进行单元测试,同时,也很难在不同界面中共享相同的行为或服务。

MVP的提出就是为了解决上述问题,它将数据显示和事件处理分离为两个不同的类 - View和Presenter,View负责将数据显示在界面上,并且将事件处理转给Presenter类。下图显示了该模式中各个类之间的关系:

这里的Model拥有View显示的数据,数据状态的改变是有Presenter控制的。

详细定义参考Martin Folwer 的 UI Architecutre

二、使用SCSF创建一个MVP模式兼容的视图

打开一个业务模块项目,在Views目录下,点击鼠标右键,选择“Smart client Factory” ->"Add View (with Presenter)",创建View向导会被打开,输入View的名字(TestView),选中“Create a folder for the view”,这样,系统会为该View创建一个单独的目录,点击完成,向导会创建以下相关的类:

  • ITestView - 该文件是一个为View设计的空的接口,Presenter使用该接口而不是具体的View实现。
  • TestView - 该类继承UserControl基类,可以在该类中设计用户界面,同时该类实现了ITestView接口并包含了一个TestViewPresenter实例,当有用户交互操作的时候,可以使用该Presenter调用相关的业务逻辑和接口。
  • TestViewPresenter - 该类继承了基础的Infrastructure.Interface.Presenter类,包含了View所需要的业务逻辑

设计视图(View)

打开TestView设计,在该界面中添加所需的控件。详细的介绍参考界面设计相关主题。

三、实现视图(View)的业务逻辑

View的设计完成后,我们就要考虑如何将数据显示在用户界面上,一般来说,在处理View的业务逻辑需要考虑两件事情,一件是如何将数据绑定到View的控件上,另外一件是如何处理事件。

数据显示:

由于View只是负责数据的显示(比如将一个Business Entity实例的变量显示),它并不知道数据是如何获取的或更新的,而数据的获取或更新是由Presenter负责,因此,为了能让Presenter将更新的数据及时通知View显示,并且Presenter不需要知道View的具体实现,因此在IView(比如,ITestView)接口中定义一些通用的接口(比如:BindDataToView(Person person))。在View的具体实现类中,我们重载该方法,将数据显示在View中。一旦Presenter知道数据发生更新,可以在Presenter中调用该接口,这样就可以通知所有对该数据更新关心的具体的View。

事件处理:

在View中需要处理的另外一件事情是如何处理View中的事件,比如Button响应事件等。对于每一个事件处理,我们可以在Presenter中定义一个方法,用来处理不同的事件,而在View中,我们需要为每个Button事件创建一个Stub方法,在该方法中调用相应的Presenter方法。对于事件的处理,我们也可以用Command或Event Subscriber&Publish模式,详细参考各自文章。

接下来的一个步骤是将视图(View)显示在Shell中

四、显示View

下列的代码是用来将View显示在Shell中的

TestView view = WorkItem.SmartParts.AddNew<TestView>("TestView");

WorkItem.Workspaces[WorkspaceNames.XXXXXX].show(view);

五、实现Presenter逻辑

前面我们提到显示在View的数据更新,事件的处理是通过Presenter来实现的,因此,在Presenter中,我们可能会调用各种各样的服务(service)来实现真正的业务逻辑,比如调用WebService Proxy。下面的任务将要告诉我们如何实现Presenter调用相关的服务(service)。

  • 如何将Service加到WorkItem中

在业务模块中,打开ModuleController类,找到AddServices方法,使用下述代码将一个Service添加到WorkItem的Service集合(Collection)中。

WorkItem.Services.AddNew(MyService)();

这样,我们就将一个Service实例添加到WorkItem的Services集合中,以便在该模块中的其他类使用。

  • 如何在View载入的时候,调用相关的Service

在View显示或载入的时候,往往会显示一些初始的数据,这是在Presenter的OnViewReady方法中实现的。同时在Presenter中,我们会定义一些服务(Service)变量,在创建Presenter实例的时候,我们需要将这些对象赋值。在这里我们利用了Injection方式来初始化这些服务。

[InjectionConstructor]

public TestViewPresenter

(

[ServiceDependency] MyService1 myservice1,

[ServiceDependency] MyService2 myservice2

)

{

_myservice1 = myservice1;

_myservice2 = myservice2;

}

在上面的代码里面,属性(Attribute)[InjectionConstructor]是应用在构造函数用来告诉ObjectBuilder当创建一个Presenter实例的时候调用该构造函数。而[ServiceDependency]属性是用来告诉ObjectBuilder去WorkItem中检索一个存在的Service实例,并将该实例作为值赋予一个变量。ObjectBuilder首先会在当前的WorkItem中寻找对应的Service实例,如果找不到,则会到上一层的WorkItem中寻找,直到Root WorkItem,当在RootWorkItem中找不到实例的话,会抛出异常。这样,我们就可以在Presenter中使用定义好的服务。

六、如何实现ISmartPartInfoProvider

当我们定义SmartPart的时候,那些使用该SmartPart的组件希望能获取关于SmartPart更多更丰富的信息,该功能是由ISmartPartInfo来实现的,在CAB中,我们定义了一个名为ISmartPartInfoProvider Interface,该接口只定义了一个方法:

public interface ISmartPartInfoProvider

{

ISmartPartInfo GetSmartPartInfo(Type smartPartInfoType);

}

该方法返回一个ISmartPartInfo,和SmartPart相关的丰富的信息可定义在里面,因此我们可以在定义View的时候实现该接口,用来提供更多的信息。

打开TestView,修改如下:

public partial class TestView : UserControl, ITestView, ISmartPartInfoProvider

实现方法如下:

public ISmartPartInfo GetSmartPartInfo(Type smartPartInfo)

{

return _presenter.GetSmartPartInfo(smartPartInfo);

}

当一个外部组件(Shell 中的Workspace)请求获取View的SmartPartInfo的时候,我们都将该请求转发给Presenter来完成。我们可以将当前View显示的数据信息通过Presenter发送给Workspace。

此致,创建一个MVP模式兼容的视图,以及相关的设计已经完成,下一章节中我们将讨论如何调用WebService。

2007年8月30日星期四

第四章 如何使用UIExtensionSites

UIExtensionSite菜单项(MenuItem)菜单工具栏(Menu strips)按钮按钮工具栏(Toolbar Strips)下面的篇幅中,将要介绍如何使用UIExtensionSite: 步骤:

添加一个UIExtensionSite

  • 注册UIExtensionSite
  • 添加一个界面元素到UIExtensionSite中
  • 绑定到一个Command
  • 书写Command处理函数
  • 一、添加一个UIExtensionSite

    在这个例子中,我们添加一个ToolbarStrips类型的UIExtensionSite。打开ShellLayoutView或ShellForm(取决于是否在创建SmartClient工程的时候创建Layout项目),在Toolbox中选中ToolStrip,添加到Designer中,打开属性,在Dock中选中Top,修改Name为“ButtonsBar”。

    在Infrastructure.Interface项目中,打开Constants.UIExtensionSiteNames类,添加如下代码:

    public const string ButtonsBar="ButtonsBar"

    将ButtonsBar的名字定义为常量,在UIExtensionSiteNames中,所有的常量必须唯一。在SmartClient中,是以名字作为一个UIExtensionSite唯一标识的。

    二、注册UIExtensionSite

    下面的代码用来注册一个UIExtensionSite

    WorkItem.UIExtensionSites.RegisteSite(UIExtensionSiteNames.ButtonsBar, this.View.ButtonsBar);

    可以将上述代码加到ShellLayoutViewPresenter类的OnViewSet()方法中或加到ShellApplication类的Run方法中(取决于是否在创建SmartClient工程的时候创建Layout项目)。

    三、添加一个界面元素到UIExtensionSite中

    打开ModuleController.cs,在ExtendToolStrip方法中将一个定义好的按钮加入先前定义好的ButtonsBar中。

    ToolStripButton element = new ToolStripButton()

    //add code here to inital element.

    WorkItem.UIExtensionSites[Constants.UIExtensionSiteNames.ButtonsBar].Add(new ToolStripButton());

    到目前为止,我们已经将一个按钮加到一个UIExtensionSite中,下一步我们将介绍如何使加入的按钮响应鼠标点击事件,并调用相应的方法。

    四、将鼠标响应事件绑定到一个Command

    在CAB中,我们可以使用Command模式来实现事件响应,打开新建模块的Constants.CommandNames类,在该类中,将该按钮鼠标响应事件命令名定义为一个常量:

    public const string TestButtonClick= "TestButtonClick";

    在ModuleController类中的ExtendToolStrip方法中,加入如下代码:

    WorkItem.Commands[Constants.CommandNames.TestButtonClick].AddInvoker(element, "Click");

    下面我们将介绍如何将Command绑定到一个方法

    五、书写Command处理函数

    在CAB中,我们使用AOP来实现Command方法绑定

    [CommandHandler(CommandNames.TestButtonClick)]
    public void OnTestButtonClick(object sender, EventArgs e)
    {
         MessageBox.Show("Successful");
    }

    CommandHandler是CAB中预订义的Attribute,用来申明事件处理方法。

    后续:

    当我们将模块相关的界面元素加到UIExtensionSite中时,如果每个模块自己添加的话,这要求每个模块开发人员需要了解Infrastructure模块的一些细节设计和实现,这对于一个大型应用开发来说是降低效率的,同时也会有很多的冗余代码。因此,我们可以将Infrastructure中的实现细节进行封装,以接口的形式暴露给各个模块,这样业务模块开发人员可以只关心自己本身的业务需求开发,而不用关心基础模块的具体实现,也减少出错的可能。

    第三章 创建业务模块

    • 在一个目录下(一般Source),点击鼠标右键,选择Smart Client Factory -> Add Business Module
    • 输入模块名字,确定。
    • 一个新的界面弹出,在该界面中,可以决定是否选中“Create an interface library for this module”。如果选中该选项,在创建业务模块的时候,会创建一个Module.Interface项目。
    • 点击“Finish”,完成业务模块的创建。
    • 创建完成后,在该业务模块项目中会生成如下几个目录:
      • Constants - 该目录包含四个类,分别是CommandNames, EventTopicNames, UIExtensionSiteNames, 和WorkspaceNames. 这四个类分别继承了Infrastructure模块中相对应的类。
      • Services
      • Views
    • 同时在ProfileCatalog.xml文件中加入如下配置。
      • <Modules>
              <ModuleInfo AssemblyFile="Module2.dll" />
            </Modules>
    • 创建向导会生成两个类,Module.cs和ModuleController.cs
    • 在ModuleController.cs中,向导自动添加了如下方法:
      • AddServices - 添加模块实现的服务
      • AddViews - 添加视图
      • ExtendMenu - 添加菜单选项
      • ExtendToolStrip - 添加快捷按钮

    Module和ModuleController的详细设计参考后续文档。

    第二章 创建SmartClient项目工程

    • Menu->file->new->project
    • 展开Guidance packages,选择smart client development
    • 输入项目名及目录,点击ok

    • 选择CAB编译好的DLL目录

            Microsoft.Practices.CompositeUI.dll

            Microsoft.Practices.CompositeUI.WinForms.dll

              Microsoft.Practices.ObjectBuilder.dll

    每个Smart Client 项目都需要上述的三个CAB dll文件。

    • 选择Enterprise Library DLL目录

    Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.dll

    Microsoft.Practices.EnterpriseLibrary.ExceptionHandling.Logging.dll

    Microsoft.Practices.EnterpriseLibrary.Logging.dll

    Microsoft.Practices.EnterpriseLibrary.Common.dll

    Smart Client application use these dlls in Enterprise Library to handle Exception and Logging.

    • 输入该项目的“根命名空间 namespace”
    • 选中第一选项可以决定是否创建一个独立项目来定义Shell的layout

    • 点击Finish
    • 此时,Smart Client 项目创建成功。

    第一章 .Net CAB&SCSF 开发包的安装

    第一步:安装Visual Studio 2005 for C#

    第二步:安装Guidance Automation Extensions - June 2006

    第三步:安装Guidance Automation Toolkit - June 2006

    第四步:安装Enterprise Library for .NET 2.0

    第五步:安装CAB 1.0

    安装完毕,用VSS2005打开Composite项目,编译Source。

    第六步:安装SCSF - June 2006

    选择CAB编译后DLL目录

    2007年4月23日星期一

    如何对待抑郁 (转至百度知道)

    1. 指定一个切合实际的想法,花的精力少,时间少的.每实现一个目标你回增加自信,这样你每天生活在成功中,生活的乐趣会逐渐体现出来,你会快乐很多.

    2. 持正常活动,千万不能懒,不能因为这样那样的原因打乱自己正常的生活习惯.
    3. 充分肯定自己,要找一个一无事处的人和找一个全能的人一样困难,每个人都有自
      己的长处.
    4. 不谈不说不听不涉及关于抑郁的事情.每天都要开开心心的.不要因为这样那样的事使得自己不开心.
    5. 让自己充实忙碌起来.约朋友吃饭聊天,花更
      多的时间在兴趣爱好方面用健康快乐的内容充满大脑,哪还有悲伤的余地?
    6. 要鼓励自己.常常微笑,开心的笑,久而久之会感觉快乐也多了些.
    7. 善待自己.自己
      把自己当作宝贝来疼惜.让自己过得好,制造幸福感,甜蜜的时候不大容易想起悲苦,相反把自己搞得颓废可怜兮兮,只会增加悲凉的气氛.




    Powered by ScribeFire.

    你为什么不快乐 (转自钱江晚报)

    前几天,好朋友相邀“聚聚”,欣然前往。席间,大家海阔天空,家长里短,倒也其乐融融。然其中一位朋友却郁郁寡欢,默默地饮酒。我知道,这位朋友近几年事
    业、家庭各方面都比较顺,不久前,孩子又考进了外地一所重点大学,在常人眼中是喜事连连。可他却说高兴不起来,工作上、家庭里烦心的事很多。比如,孩子在
    外地总是不放心,生怕他学习上不努力,学坏样等等。





      我知道,这位朋友的思维是进入了一个死角。他看问题的视角是负面、消极的。尽管在旁人眼中,他处在幸福之中,可他感觉不到幸福,却为一些并不存在的事
    忧愁,被种种的可怕念头纠缠。我说,老兄,船到桥门自会直,车到山前必有路,孩子的事,就让孩子自己去解决,不要太跟自己过不去。





      于是,我想到了这样一个问题:人为什么会不快乐?为什么有些人尽管身处逆境,却整天乐呵呵?有些人事事顺意,却仍然郁郁寡欢?说到底是一个思想意识问
    题。弥尔顿在《失乐园》中有一句话:“意识本身可以把地狱造就成天堂,也能把天堂折腾成地狱。”我认为是比较直观地讲出了其中的道理。我们每个人的烦恼和
    痛苦都不是因为事情的本身,而是我们看问题的观念和态度。这位朋友就是因为观念比较悲观,结果无形之中给自己增加了许多的压力,把天堂折腾成了地狱。





      在生活中经常不快乐的人,一种是思想比较狭隘。这种人,一件小事往往看得很大,很严重。一种是思想比较敏感,明明是在说别人,他却认为是在影射他,神
    经过敏,疑神疑鬼,心里不痛快。还有一种是思想悲观。一事当前,总是如履薄冰,如临深渊。在困难中看不到希望,在胜利时又时时担心出问题。“人生不满百,
    常怀千岁忧”。这种人,该快乐时快乐不起来,而有了事情就更是沮丧、悲哀了。





      著名作家张贤亮写过一篇《心安即福地》的文章,我看了很有同感。在这篇文章里,他回忆了自己18岁从北京携老母弱妹来到宁夏,后来年过不惑而孑然一
    身,为省一角钱而步行十五公里去乘车的经历。是的,世事万物即在心,心安了,人也乐了。心不安,即使锦衣玉食、华屋豪车,同样不会快乐。约翰·奈斯比特
    说:“我们必须学会把技术的物质奇迹和人性的精神需求平衡起来。”





      朋友,在当前越来越激烈的竞争中,努力学会在协调好外部环境的同时,注意调理好个人的内心世界。记住:天堂与地狱,就在你心中。



    Powered by ScribeFire.

    2007年1月25日星期四

    面试

    最近参加了西门子的面试,一路过关斩将,已经到了最后一步(和德国总部老板面试),突然心里很平静,没有前两关的那种紧张和兴奋,因为我知道不管最后结果怎么样,我肯定不会去的,呵呵,因为我不希望因为工作而给家庭带来不应有的动荡。

    有时候取舍是很难的,不过就像我以前说的,我不会贪婪的!我只需要一样,对我最重要的一样!