tag:blogger.com,1999:blog-284621792024-03-16T18:08:26.945+11:00James CrispRuby on Rails, C#, .NET, book reviews, film reviews, mind hacks, Wing Chun and the occasional personal bit.James Crisphttp://www.blogger.com/profile/00769345740252337538noreply@blogger.comBlogger2125tag:blogger.com,1999:blog-28462179.post-85563568654296666912007-01-12T11:51:00.000+11:002007-02-25T22:59:39.651+11:00AntiPattern: BusinessObjects in the driving seatWhen you have a rich domain model with a business object centric design, and a Windows forms GUI, it can be very tempting to start putting significant process logic in the business objects. After continuing along this path a little further, you may realise that the process needs some sort of user input, and you use events or some sort of notifier pattern to gain user input required by the process, while still maintaining layering in terms of referencing. Then additionally you may need to access some sort of external service.<br /><br />Here is an example:<pre>class Order : BusinessObject<br />{<br /> public void SendOrder(INotifier notifier)<br /> {<br /> if (ReadyForDelivery ||<br /> Confirm("Are you sure you want to send order lines?"<br /> + " They are not ready for delivery."))<br /> {<br /> OrderLine[] orders = GetLinesToSend();<br /> foreach(OrderLine line in Lines)<br /> {<br /> SendLine(line); // send line using a web service?<br /> }<br /><br /> Notify("Lines sent successfully.");<br /> }<br /> }<br />}<br /><br />interface INotifier<br />{<br /> void Notify(string msg);<br /> bool Confirm(string msg);<br /> OrderLine[] GetLinesToSend();<br />}<br /></pre>I would like to suggest that this is an anti-pattern and a trap. Although there is no direct reference from the Business Layer to the GUI layer (INotifier is implemented in GUI and passed down), the Business Layer now requires the ability to stay instantiated, pause while waiting for responses from the notifier, and then continue execution. This will work for rich client applications, but not in a stateless web environment. The ideal of being able to swap in/out the GUI layers on top of the Business layer is now compromised.<br /><br />Instead, it would be possible to drive form the GUI layer, and call a service to send the Order Lines. In pseudo code below:<pre>void SendMenu_Click(...)<br />{<br /> if (Order.ReadyForDelivery ||<br /> MessageBox.Show(...) == DialogResult.Yes)<br /> {<br /> using (ChooseLineForm chooseLineForm =<br /> new ChooseLineForm(Order))<br /> {<br /> chooseLineForm.ShowDialog()<br /> }<br /> SendingSevice.SendLines(chooseLineForm.selectedLines);<br /> ...<br /> }<br />}<br /></pre>If the logic in the GUI layer became much more complex, it may be a good idea to pull it out into its own class (eg, LineSender). This class would be a type of GUI level controller, responsible for orchestrating the send process.<br /><br />Using this approach, there are a number of benefits:<br /><ul><li>BusinessObjects have no reliance on GUI implementation, so can be used for Rich Client and Web Client indiscriminately.</li><li>Web developers are free to implement the user input process in stateless way more appropriate to their platform.<br /></li><li>Functionality for sending Order lines (some sort of integration with a web service?) is pulled out into a service class which can be reused elsewhere (potentially sending other types of objects?) and unclutters the Order business object and removes its dependency on an external service.</li><li>Code is simpler and easier to follow.</li></ul>James Crisphttp://www.blogger.com/profile/00769345740252337538noreply@blogger.com24tag:blogger.com,1999:blog-28462179.post-53460954012389009602007-01-11T09:56:00.000+11:002007-01-11T09:59:32.191+11:00In Defense of Simplicity AND Complexity<a href="http://www.scottberkun.com/blog/?p=502">Simplicity</a> and <a href="http://www.joelonsoftware.com/items/2006/12/09.html">complexity</a> seem to have become hot topics for some of my favourite technical bloggers of late. These fine people have taken the view that things should be either simple or complex. Right, seems logical, these are opposites. However, I would like to suggest that in a well designed appliance which addresses a complex process, it should have both a simple AND a complex interface.<br /><br />A couple of years ago, I bought a LG "Fuzzy Logic" washing machine. It has lots of buttons and settings on the front and one big button that says something like "Start". 97% of the time, I throw in my washing, some detergent and press the big start button, and the washing machine works out all the settings, displays them and then starts. In the 3% of the time when I want to do something different (eg, just a rinse), I use the more complex part of the interface to change the 'cycle' settings.<br /><br />Recently, I bought an IXUS 65. It's a lovely digital camera, and it provides both a complex and a simple interface. As soon as I put in the battery, I was able to take pretty nice pictures by just clicking the big button on the top. No problem, I was very happy. Over the next few days, I glanced through the manual and fiddled with more complex settings for ISO, colour etc. However, in 95% of shots, I simply want to click the one big button that takes a nice auto-everything picture. It's only occasionally that I want to change the settings to achieve a particular effect or to override a mistake in the auto settings.<br /><br />To conclude, I think that my talented fellow bloggers are all right. People like complex interfaces and simple interfaces, just at different times, for different tasks. The best gadgets and appliances offer both.James Crisphttp://www.blogger.com/profile/00769345740252337538noreply@blogger.com42