Results of the laptop review:
Build solution of the DeltaShell, 101 projects. (heh?!)
First Second ------- ------- HDD 7.2k: 305 sec 37 sec SSD: 155 sec 27 set +50% +27%
And the winner is:
Windows 7 124 sec!
I tried to build everything using command-line tool. Speedup is 27-50%. In Windows 7 it shows even more decrease in compile time.
Hd Tach test results:
After testing a bit later, I've got strange results. Performance degraded for no reason to ATA-100 (133Mb/s). Still faster compare to HDD but strange.
Then after googling a bit and reading blogs I've found out that actually you have to do many things in XP to make SSD work smoothly. Mainly because OS was not designed for them. As a results performance will degrade in time. See Performance Degradation Over Time, Wear, and Trim for more details. The conclusion is to try Windows 7 and see what happens there.
DON'TS:
- Don't dublicate subscriber / consumer logic of event.add/remove by introducing your own interfaces simulating it.
Instead of introducing the following code in the framework:
namespace DelftTools.Gui { public interface IGuiObjectSelectionPublisher { /// <summary> /// Gets or sets current selected object(s). /// Visibility of the menus, toolbars and other controls should be updated when selected object is changed. /// Default implementation will also show it in the PropertyGrid. /// </summary> object Selection { get; set; } /// <summary> /// Fired when user changes selection by clicking on it or by setting it using Selection property. /// </summary> event EventHandler SelectionChanged; } } namespace DelftTools.Gui { public interface IGuiObjectSelectionSubscriber { ///<summary> /// Subscribes the action to the publisher ///</summary> ///<param name="action">The action to subscribe</param> void SubscribeAction(Action<object> action); ///<summary> /// Unsubscribes the action from the publisher ///</summary> ///<param name="action">The action to unsubscribe</param> void UnsubscribeAction(Action<object> action); } } namespace DelftTools.Gui { ///<summary> /// This class is part of a more loosly coupled publisher subscriber pattern where /// IGui is the publisher. Subscribers can be used anywhere in the application /// Most of time this will be the plugins or view presenters that will listen to /// selected object changes ///</summary> public class GuiObjectSelectionSubscriber : IGuiObjectSelectionSubscriber { private readonly IGuiObjectSelectionPublisher publisher; private readonly HashSet<Action<object>> actions; ///<summary> /// Constructs the subscriber ///</summary> ///<param name="publisher">The publisher to observe changes from</param> public GuiObjectSelectionSubscriber(IGuiObjectSelectionPublisher publisher) { this.publisher = publisher; this.actions = new HashSet<Action<object>>(); } ///<summary> /// Subscribes the action to the publisher ///</summary> ///<param name="action">The action to subscribe</param> public void SubscribeAction(Action<object> action) { actions.Add(action); if (actions.Count == 1) { publisher.SelectionChanged -= OnSelectedObjectChanged; publisher.SelectionChanged += OnSelectedObjectChanged; } } ///<summary> /// Unsubscribes the action from the publisher ///</summary> ///<param name="action">The action to unsubscribe</param> public void UnsubscribeAction(Action<object> action) { actions.Remove(action); if(actions.Count == 0) publisher.SelectionChanged -= OnSelectedObjectChanged; } /// <summary> /// Handles the internal IGui SelectionChanged events. The handler /// will use the selected object as the argument value in the action /// </summary> /// <param name="sender"></param> /// <param name="args"></param> private void OnSelectedObjectChanged(object sender, EventArgs args) { foreach (var action in actions) { action(publisher.Selection); } } /// <summary> /// Remove all referencences /// </summary> ~GuiObjectSelectionSubscriber() { if (actions.Count == 0) return; actions.Clear(); publisher.SelectionChanged -= OnSelectedObjectChanged; } } }
... and using it like this (in every presenter):
namespace DelftShell.Plugins.NetworkEditor.Forms.CompositeStructureView { public class CompositeStructureViewPresenter : Presenter<ICompositeStructureView>, ICanvasEditor { private readonly IGuiObjectSelectionSubscriber subscription; private readonly Action<object> selectObjectInViewsAction; ... public CompositeStructureViewPresenter(IGuiObjectSelectionSubscriber subscription) { selectObjectInViewsAction = (e => { var structure = e as IStructure; if (structure != null) SelectObjectInViews(null, structure); }); this.subscription = subscription; this.subscription.SubscribeAction(selectObjectInViewsAction); } ... } NetworkEditorViewProvider.cs: var presenter = new CompositeStructureViewPresenter(new GuiObjectSelectionSubscriber(Gui)); presenter.ViewProvider = Gui.ViewProvider;
Just use:
NetworkEditorViewProvider.cs: var presenter = new CompositeStructureViewPresenter(new GuiObjectSelectionSubscriber(Gui)); presenter.ViewProvider = Gui.ViewProvider; Gui.SelectionChanged += new WeakEventHandler<SelectedItemChangedEventArgs>((sender, args) => { if (args.Item is IStructure) { var structure = (IStructure)args.Item; compositeStructureViewPresenter.SelectObjectInViews(null, structure); } });
The code is much shorter and completely replaces all the logic above without introducing unnecessary complexity to the framework. One more good thing is that it is better to keep things loosely coupled instead of putting gui selection logic into every specific presenter, just having it in the presenter/view factory class is good enough. There is no need for a CompositeStructureViewPresenter to depend directly on a framework selection logic IGuiObjectSelectionSubscriber, it will be asked when to select things. Control over when it will be asked still stays in a plugin (view provider).
Keep in mind that DelftShellGui and NetworkEditorViewProvider are in this case linked in a weak way so once a view will disappear - subscribtion will be garbage collected.
I really hope that Microsoft will add it as default feature in .NET 4.0 or SP1, something like += weak delegate {...}. You can vote here to get it implemented in the next .NET.
By the way, instead of redirecting selection to a presenter it might be better to make it work in a view (but probably then we need to introduce a Iview.Selection mechanism first):
Gui.SelectionChanged += new WeakHandler<SelectedItemChangedEventArgs>((sender, args) => { if (args.Item is IStructure) { compositeStructureView.SelectedStructure = (IStructure)args.Item; } });
References:
Sometimes pasting strings from a file into a source file is awkward. Use SmartPaster 2008 to paste the
strings nicely formatted with newline characters etc. You can download the file here
http://cid-86665d02cd7ef5cf.skydrive.live.com/self.aspx/Public/SmartPaster2008.AddIn.zip
Copy the contents into C:\Documents and Settings[yourname]\My Documents\Visual Studio 2008\AddIns (you may have to
create the AddIns folder). You now get this menu in vs 2008
Problem
The forms in a smart client application frequently contain various controls, handle user events, and contain logic to alter the controls in response to these events. Writing this code in the form class makes the class complex and difficult to test. In addition, it is difficult to share code between forms that require the same behavior.
Solution
Example code
interface IShapeView { IList<Shape> Shapes { get; } void SelectShape(Shape shape); void UnSelectAll(); void Refresh(); } class ShapeView : UserControl, IShapeView { private readonly Presenter presenter; private readonly Button addShapeButton; public View(Presenter presenter) { this.presenter = presenter; this.Shapes = new List<Shape>(); this.addShapeButton.Click += AddShapeClicked; } public IList<Shape> Shapes { get; } private void AddShapeClicked(object sender, EventArgs args) { this.presenter.AddNewShape(); } public void SelectShape(Shape shape) { // select shape on canvas // Refresh the view (can also be done through events) this.Refresh(); } public void UnSelectAll() { // un select all shapes on canvas and refresh this.Refresh(); } public void Refresh() { // refresh the canvas } } class ShapeViewPresenter { IShapeView View { get; set; } public void AddNewShape() { // Create shape geometry.. var newShape = CreateNewShape(); // Add new shape logic to model and view.. View.Shapes.Add(newShape); //Select the new shape in the view View.SelectShape(newShape); } private static Shape CreateNewShape() { // create or get the shape from a repository return new Shape(); } } class Shape { // The model }
Advantages
• Clean seperation of concerns
• Simple views wich can easily re-factored by replacing UI components or complete views implementation without big changes in the view logic wich resided in the presenter
• Unit testing presenter is easier then unit testing the view
Disadvantages
• The pattern is complex and may be unnecessary for simple screens.
• The pattern is one more thing to learn for busy developers: there's some overhead.
• It can be hard to debug events being fired in active Model-View-Presenter.
My personal view is that even if you think this is a useful pattern (and it is) you shouldn't use it indiscriminately on every screen in your application. You should use it where you have reasonably complex logic which will benefit from splitting the user interface classes in this way.
Conclusion
Use only when view logic gets complex. For simple views it is easier to leave out the presenter.
One hbm.xml file per class directly next to the class file.
I know there are exceptions (SharpMapGis.hbm.xml) but this is how it should be.Say as little as possible in your hbm.xml
so don't:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" auto-import="false"> <class name="DelftTools.DataObjects.Functions.IFunction, DelftTools.DataObjects.Functions" table="function" lazy="false" > <id name="Id" column="id" type="System.Int64" unsaved-value="0"> <generator class="increment" /> </id> <discriminator column="type" type="string"/> <property name="Name" column="name" type="string" /> </class> <class name="DelftTools.DataObjects.Functions.IVariable, DelftTools.DataObjects.Functions" table="function" lazy="false" > <discriminator column="type" type="string"/> </class> </hibernate-mapping>
But let nhibernate handle naming of tables and columns etc. This has an advantage of controlling the naming in a general way (NHibernate let's you configure naming conventions) and leaves you refactor proof. Also dont use column names,types tables etc.
So you get:
<hibernate-mapping xmlns="urn:nhibernate-mapping-2.2" namespace="DelftTools.DataObjects.Functions" assembly="DelftTools.DataObjects.Functions" auto-import="false"> <class name="IFunction" lazy="false" > <id name="Id"> <generator class="increment" /> </id> <discriminator column="type" type="string"/> <property name="Name" /> </class> <class name="IVariable" lazy="false" > <discriminator column="type" type="string"/> </class> </hibernate-mapping>
Also check this post by Ayende about best practices: http://ayende.com/Blog/archive/2008/07/24/How-to-review-NHibernate-application.aspx
note: Unfortunately Nhibernate has some awkward defaults (like lazy classes) that require us specify lazy=false everywhere (lazy introduces some extra problems and should not be used as a default i think) maybe we can change the defaults?
Since testing classes in isolation is a good thing it is nice to be able to have a quick dummy implementation of an interface without having to instantiate the object (and needing a reference to a concrete class). Why mocking is good can be found in many posts (see Gena's post here http://wiki.deltares.nl/pages/viewpage.action?pageId=5272)
What is stubbing? Stubbing is quickly creating dummy instances of interfaces. Stubs are not used to test behaviour (calls on objects). Mocks are used for that.
This is a quick how-to stub with RhinoMocks. It is meant as a reference. When you want something stubbed-out in your test and don't know the syntax it might be here (hopefully . In that it would be nice to expand this post.
Setting it up.
To stub you need a mockrepository. Set it up some where in your (test)class:
private static readonly MockRepository mocks = new MockRepository();
Properties with getter/setter
interface IInterface { string Name{ get;set; } }
Can be used directly since the default property behaviour of stubs gives us a getter setter
var mock = mocks.Stub<IInterface>(); mock.Name = "lee";
Readonly properties
Given an interface with a readonly property:
interface IInterface { string ReadOnly { get; } }
We can use it like this in test
var mock = mocks.Stub<IInterface>(); mock.Stub(a => a.ReadOnly).Return("kees"); mocks.ReplayAll();//don't forget or you will get null
Unfortunately our syntax gets more complex and we need to turn on the stub using mocks.ReplayAll();
Mocking void methods
Methods without return values are easy. You get default implementation doing nothing
interface IInterface { void Go(); }
We can use it like this in test
var mock = mocks.Stub<IInterface>(); mock.Go();
Mocking method with return values
What if you need a method to return a specific value?
interface IInterface { string GetMyString(); }
Use like:
var mock = mocks.Stub<IInterface>(); mock.Stub(a => a.GetMyString()).Return("kees"); mocks.ReplayAll();//don't forget or you will get null
Mocking methods with parameters and return values
interface IInterface { string GetMyString(string a); }
Always returning the same value
var mock = mocks.Stub<IInterface>(); mock.Stub(a => a.GetMyString(null)).IgnoreArguments().Return("kees"); mocks.ReplayAll();
Returning based on input
mock.Stub(a => a.GetMyString("rock")).IgnoreArguments().Return("paper"); mock.Stub(a => a.GetMyString("paper")).IgnoreArguments().Return("scissor"); mocks.ReplayAll();
Resulting in rock->paper and paper->scissor
Helping the mock object out of its verified state
Suppose you have the System.InvalidOperationException: This action is invalid when the mock object is in verified state
You can't use a mock in Rhino Mocks after its expectations were verified, even if you're calling a method that does not make part of your expectations.
To solve this use the following:
[TearDown] public void TearDown() { mocks.BackToRecordAll(); if (testee != null) testee.Dispose(); } [Test] public void Test() { // Expectations setup someInterface.DoStuff(); mocks.ReplayAll(); // Replay testee.SomeInterface = _someInterface; testee.DoSomeOtherStuff(); mocks.VerifyAll(); }
If someone checks in a commit you might want to undo it.
Howto
1 Open repository browser and switch to revision just before the fatal commit
2 Copy src of this revision to src_before_commit
3 Switch back to HEAD revision
4 Replace src with src_before_commit (delete and rename)
Since the Morphan Duros model uses matlab to run its model it needs matlab to run some tests. A new category
is introduced to identify these matlab tests (Category("Matlab")). These tests are run on a buildserver (1716) which has
the matlab environment installed. To run these tests locally you need to install matlab from
https://repos.deltares.nl/repos/delft-tools/trunk/shared/Matlab