December 2007 - Posts
While reading materials about how to improve my OO code / design, I run into "Tell, Don't Ask" principle. Interestingly, I also have read this article and realized that I am still thinking as a procedural developer. But then I got confused by the idea - you can test the interactions, but how do you test the state if you trying to eliminate any trace of state from the object? Does that mean that state base testing causes to violate TDA principle?
This is a question to community - ideas are appreciated.
PS: I was trying to pretend a situation where needed to report a subject without accessing subject's properties - using what I thought would be a TDA principle. Same question remains.
One of the web applications requirements is to provide a rich user experience. Client side validation and formatting is a part of this UX. The subject I want to address today is how to achieve a good level of UX on formatting with respect to one of the OO principles, DRY principle.
The case is simple, user can edit multiple date inputs, that are reformatted right away. The screen would look like this:
| Item #1 delivery date: | |
| Item #2 delivery date: | |
| ... | |
Where's the DRY issue is raising - formatting can be done on server side and on the client side. One of the requirements is to reformat the value right as it is entered. One of the options is to use Ajax - well, a suicidal option. Another one, to invoke some client side code (client presentation logic?) to do the formatting. But as soon as this is done, the logic is replicated on server and client. Or is it?
The solution I go with is to have the logic centralized in a single location, execution of the logic done in different places. Having formatting rule in one location would allow to 'downsize' the replication of things. Formatting string identical to the one that .NET has will be passed to the client side code (JavaScript). That same code will leverage something like regular expression (or anything else that will assist reformatting).
So how dry is that? Probably not the best solution, so what are your ways to solve this?
The training session I took with JP Boodhoo "Nothin But .NET" was awesome. Was quiet surprised that a variation of this course, "Nothin But .NET Fundamentals" is not sold out yet. If you are anywhere near to College Station TX, and want to know what high-end fundamentals are - register to this training session.
JP is a great guy and an awesome trainer. If you looking for challenge - you will get it. Fundamental will never be the same after you go through the session.
PS: As an ex-trainer I can assure you that you getting a high-class experience with no "canned" and "chewed" content. And this is rare these days.
This post is not going to be technical at all - pure theory of how to generate a change in minds of those who cannot accept what agility and test driven development are proposing.
One of the biggest questions is "why". Why would someone bother to code to interfaces, if could deliver a working application without it. Why to have the hassle of creating test first, interface and then concrete implementation, going through enormous amount of code changes, if you can code the class, and in 'worse' case extract an interface 'just-in-case'? Why to give a method a fluent name and worry about simplicity, if you can 'dig the code to see what it's doing'? Why to bother test in isolation, if you can do the integration test. Hell, why even to bother doing integration, let the user do the testing...
So I tried to step back, and rethink how to generate the change in minds, because once the mind is accepting the idea, techniques will definitely come after. One of the ideas I am trying to stick to is to serve an example (thanks JP for constantly reminding this) - let others see that you are standing behind your words and don't be afraid of admitting the fact that the learning curve for you has the same slope as for others.
Keep challenging those that are in doubt - do not let them stay in the cozy spot thinking that since they won a single argue, they won the whole battle.
Figure out the weak spots in the old school doctrine, and show how you can make it better.
Experiment and benchmark - the best way to blow away assumptions is to show how they fail in reality. Get someone to read a procedural code of a page and a half, or show how a call to stand-alone utility method fails the logic of an average developer to understand why there's a need to go to a utility that has no relationship to the subject at all.
Give them the material for a thought. The true developer wants to know what's behind the door. If you leave the door slightly opened, the real developer will have a sneak look through it. And if so, then allow some time for ideas to be digested. It will grow in something bigger out of a curiosity. And if it won't, well, that was just a first level. The game is more appealing at the next one - keep trying!
User Controls are handy when working in web forms, but what a mess they can generate. I was asked what to do when UCs are used and some dependencies need to be injected during the construction - but UCs are a bit tricky in regards to construction. So the possibilities are:
1. Use new operator and instantiate a user control (Web Application Project) - no good as the visual elements residing on the designer surface (.ascx) then not loaded.
2. Use Page.LoadControl(<path>) - but no option to pass in parameters.
3. Use Page.LoadControl(<type>, params object) - not strongly typed.
So all these possibilities are nice, but not helping to use a load with strongly typed parameters. Then the idea proposed at one of the replies with almost the same question was to use a static factory. I tried to play with the idea and this was a result.
Step 1 - create the UC
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SomeUserControl.ascx.cs" Inherits="LoadControlWithFactory.SomeUserControl" %>
<asp:TextBox runat="server" id="txtName"></asp:TextBox>
|
Step 2 - create the code behind with static factory method
1: public partial class SomeUserControl : UserControl 2: { 3: private string name; 4: 5: protected override void OnLoad(EventArgs e) 6: { 7: base.OnLoad(e); 8: txtName.Text = name; 9: } 10: 11: public static SomeUserControl Create(string name) 12: { 13: SomeUserControl some = ((Page)HttpContext.Current.Handler).LoadControl("~/SomeUserControl.ascx") as SomeUserControl; 14: some.name = name; 15: return some; 16: } 17: }
|
Note: the underlined code has a bad smell - but that was the only idea I had to gain access to the currently executed page. Any other ideas are welcomed.
Step 3 - load UC dynamically through the code with injected data
1: public partial class _Default : System.Web.UI.Page 2: { 3: protected override void OnPreRender(EventArgs e) 4: { 5: base.OnPreRender(e); 6: phContent.Controls.Add(SomeUserControl.Create("Sean Feldman")); 7: phContent.Controls.Add(SomeUserControl.Create("Anna Feldman")); 8: } 9: }
|
Conclusions
What it seems is that this allowed a few more things than just a pattern implementation. It allowed:
- DRY principle - rather than replicating the .ascx path wherever UC is loaded, this information is now stored and encapsulated inside the factory.
LoadControl("~/SomeUserControl.ascx") as SomeUserControl; // for Sean
LoadControl("~/SomeUserControl.ascx") as SomeUserControl; // for Sean
- Simplicity - Drop Dead Simple principle (well, this is something I like to apply recently to the code to make is easy to digest, so this is the name I came up with).
SomeUserControl.FactoryMethod(<typed params>); |
- Maintainability - simple and affordable.
Update 2007-12-17: I have re-arranged slightly the post to minimize clipping and attached the code.
While discussing with JP Boodhoo why he stopped to use the I notation for the interfaces, I think we got to the point where it was clear why would someone drop the "I" or opposite, adopt it.
As a developer, I want to differentiate between a pure abstraction and a concrete thing. So to ease on ourselves, we put the I as a differentiation, rely on the visual interpretation that our brain (little one in my case) is doing ("association" as against to "memorization"). And that would be the justification of using the "I" notation.
Now, if we look at the same issue from a more real-world perspective - bicycle. A bicycle is an abstraction, a 3-wheel or mountain bicycle are something concrete. So having something like:
1: class MountainBicycle : Bicycle 2: { 3: }
|
Is nothing but
1: class MountainBicycle : IBicycle 2: { 3: }
|
With a difference that you know that bicycle is an abstract thing and if your brain is trained enough about it, then you do not need to have an "I"-hint to trigger the "association".
Personal note: so far, from the comments to my previous post on this, I have not seen that direction. Does this mean we are "boxed" to a particular thinking and not willing to evaluate other options as a community (.NET)?...
PS: "Hey, what about Customer sample?" you might ask - never too late to admit - I was wrong. Customer is not concrete, therefor it's an interface, what concrete is a CertainTypeOfCustomer or any other deviation of a Customer :)
While reading R.C. Martin's book converted to C# by M. Martin "Agile Principles, Patterns, and Practices in C#" I could not ignore the fact that the Java notation for interface naming was used all over the place. Trying to be open-minded (or should I use "pragmatic" these days) I want to pop a question what is the benefit of dropping the I-prefix and how it does or does not influence the daily work.
For myself, having an "I" prefix in front of the name not only tells me that this is an interface, but also that this is a pure "contract" (Design by Contract is something I start to like).
1: public interface ICustomer 2: { 3: // ... 4: }
|
1: public interface Customer 2: { 3: // ... 4: }
|
So what do you have to say about it? To "I" or not to "I"?
I have installed .NET Framework 3.5 along with already existing 2.0 as a part of Visual Studio .NET 2008 installation. What a surprise it was to find out that the old "web site" projects were all broken... after a few hours of investigation, my coworker, Glen and I have found that the 3.5 is not so innocent and it writes to 2.0 new version of assemblies. Why in the world it would do it?! So far this is under MS engineers investigation and I hope it was an error on our side.
And this KB can be useful for some people as well: KB941824 - at the 'cause' section, in little font I loved the note: "When you install the .NET Framework 3.5, the .NET Framework files in the V2.0.50727 folder are updated. Therefore, when you install the .NET Framework 3.5, Visual Studio 2005 is affected." Great...
2007-11-28 21:25 Update: a quick example of breaking code is attached in zip file. The problem is in RuntimeMasterPageFile property at compile time. Issue20071128.zip
2007-11-30 00:15 Update: after recreating the whole environment step by step I reproduced the issue and seems like the breaking change is in web.config under system.web section - one of the configurations, <page> has an attribute pageBaseType that I was using and didn't have to specify anything on each single page. After 3.5 install, which is also a SP1 for 2.0, this feature is no longer respected by compiler. Keep tuned for updates.
2007-12-03 Update: ASP.NET team confirms that this is a bug in 3.5 (2.0 SP1) and they will release a hotfix within up to 4 weeks.
2008-03-05 Update: The fix was built, but failed one of MS internal test stages. Therefore, they have moved it back to the previous stage for rebuilding. Updates on the status will be posted as that process continues.
More Posts