Sean Feldman's profileברוכים הבאיםPhotosBlogLists Tools Help

Sean Feldman

Occupation
Interests
The more I earn, the more I realize how little I know.
Photo 1 of 14
No list items have been added yet.

ברוכים הבאים

7/23/2008

Moved.

The blog has entirely moved to my main blog.

Break It Down Into Bits

I had to refactor a portion of code and decided to go with strategy pattern. Interesting thing is that the final result might look more complex, but when discussed with a fellow developer, got green light in terms of "more maintainable" and "self documenting" code result. So here I am sharing it with others for review and opinions.

The problem

A person is associated with a plan it is member of. Association is expressed in a plan code assigned to the person. Based on the code a person is assigned, different fields from his plan details record are pulled into calculation. Possible plan codes are PlanA, PlanB, PlanZ. Each plan is driving out the price for member, spouse, and total costs. Fields involved in calculations are:

  • For PlanA:
    • MemberCost = PlanAMember1 + PlanAMember2
    • SpouseCost = PlanASpouse1 + PlanASpouse2
    • TotalCost = MemberCost + SpouseCost
  • For PlanB and PlanZ - same story

The original code was using reflection and retrieving values based of reflective code that extracted property values based on the fact that attributes (properties) of an object would have the names that are consistent and are prefixed with the plan code. The code then would do everything-in-one-shot.

   1:  var planDetails = PlanDetails.Load();
   2:  Type type = typeof(PlanDetails);
   3:  double memberCost 
   4:     = type.GetProperty(planCode + "Member1").GetValue(planDetails, null) 
   5:     + type.GetProperty(planCode + "Member2").GetValue(planDetails, null);
   6:   
   7:  double spouseCost = 
   8:     type.GetProperty(planCode + "Spouse1").GetValue(planDetails, null) 
   9:     + type.GetProperty(planCode + "Spouse2").GetValue(planDetails, null);
  10:   
  11:  double totalCost = memberCost + spouseCost;

What are the down sides of this code - fragility.

  • Plan code found for a person might not be in the database, the code will explode
  • When PlanDetail property(s) name is different from the assumed pattern, the code will definitely break
  • Not flexible - calculations logic might vary in the future and that will over complex everything-in-one-shot code
  • Readability of the code lucks simplicity - overwhelming details

Strategy sounded like a right ways to go. Divide and rule - split each plan calculations into its own class - PlanA, PlanB, and PlanZ. Also adding a Default plan to have a fallback mechanism. To make it all sing, a factory would create one of the plans based on the required argument - plan code. To glue it all together an abstraction for all plans is required. I considered an interface first, but since the plans share the calculations at this point, decided to do the simple thing - abstract base class Plan that would capture all the similarities and leave the descendents to fill the rest. This is an oversimplified result code (removed extra details and client-associated stuff).

Factory

   1:    public class PlanFactory
   2:    {
   3:      public static GetPlanFor(string planCode, IPlanDetails planDetails)
   4:      {
   5:        switch (planCode)
   6:        {
   7:          case "PlanA":
   8:            return new PlanA(planDetails);
   9:          case "PlanB":
  10:            return new PlanB(planDetails);
  11:          case "PlanZ":
  12:            return new PlanZ(planDetails);
  13:          default:
  14:            return new Default();
  15:        }
  16:      }
  17:  }

Plan

   1:  public abstract class Plan   
   2:  {   
   3:       public readonly IPlanDetails planDetails;
   4:   
   5:       protected Plan(IPlanDetails pd)
   6:       {
   7:         planDetails = pd;
   8:       }
   9:   
  10:        public abstract double MemberCost { get; }   
  11:        public abstract double SpouseCost { get; }   
  12:        public double TotalSpouseCore    
  13:        {    
  14:          get { return MemberCost + SpouseCost; }    
  15:        }   
  16:  }

PlanA (similar are PlanB and PlanZ):

   1:  public class PlanA : Plan
   2:  {
   3:       public PlanA(IPlanDetails pd) : base(pd) {}
   4:   
   5:        public override double MemberCost
   6:        {
   7:          get { return planData.PlanAMember1 + planData.PlanAMember2; }
   8:        }
   9:  }

Usage:

   1:  var plan 
           = PlanFactory.GetPlanFor(user.GetPlanCode(), PlanDetails.Load());
   2:  double memberCost = plan.MemberCost;
   3:  double spouseCost = plan.SpouseCost
   4:  double totalCost = plan.TotalCost;

Now comparing the last chunk of code to the original code - some difference.

Conclusions

With simplified for maintainability and readability code, the complexity went up significantly. With power comes responsibility - if you want code that is easy to maintain and change, test and trace, you have to lift your skills and play by the rules. And the rules are simple

  • Strive to have a network of objects each handling a single responsibility, rather than procedural one giant class that does it all
  • Learn core principles (patterns, idioms, etc)
  • Don't be afraid of complexity if it is based on core principles

PS: to spice it up, the real code did actually have a more sophisticated behaviour down the road, which was taken into the Plan code (in case it is shared by all plans) or into individual plans when it's unique to that particular plan. The bottom line is the the 'user' code, the usage of the factory, has not changed at all, and the details of each plan where left to the plans themselves, a place where they naturally belong.

PSS: there's something bugging me down - the switch statement in the factory. I would rather have something that would eliminate that switch statement as it feels not right. Ideas?

7/15/2008

DB Trigger - A Friend Or A Foe?

Database triggers are useful, and I am not going to bush it completely. In some cases, like the one I run into, triggers are more of a distraction and source of issues, rather than help and ease of headache-free maintenance. In order to understand the case, players must be introduced first.

  • An application that collects information from user inputs to be stored in database at a very specific table that is uniquely assigned for the purpose of persisting user selections.
  • An external service that is asked from time to time to perform a job based on the inputs user has provided from the application.
  • Results of the job are stored in database, and for optimization purposes, some metadata stored as well, in a table of its own. What kind of metadata? Well, lets keep it simple and say that a certain job was executed or not. So the next time job (pretend that it's scheduled) has to be run, it will first validate that it wasn't executed before.

Some business process rules around the user inputs are defined as well

  • Once a user has updated inputs from the application, any scheduled job running after the fact inputs were changed, has to ignore the fact that the job was run before in order to take in account the new inputs.

What is the standard DB approach and the simplest one to implement - put triggers in place. This is an absolutely valid approach. You observe the Inputs table, on updates to that table you trigger updates to the Metadata table and voilà it's working. Each time user makes an update to inputs, metadata is wiped and job is forced to re-run the calculations when it kicks in. Simple, elegant, but non trivial down the road.

The application evolves, you add down the road more inputs and suddenly - the magic of triggers is done. You validate the fact that they are in place, but it is very easy to skip the fact that within the trigger the newly added fields to the inputs table are not processed.

Another scenario - you want to be able to test the code, and see that changes to the inputs are actually triggering the metadata changes. But how would you do it, unless running in a debug with a real database attached?

One idea is to remove the triggers from the database and implement them in the code, after all it is really an application behaviour we are trying to capture and express. Depending on how data access is implemented, the way to implement the code differs. We still are using home grown sort-of entities framework (hopefully not for long), and inputs table has a reflection in the application as an object of it's own. Initial idea was to create a proxy and it would update the metadata once inputs are persisted. Due to technical limitations of the framework we are using, the implementation went in a different technical route, but still, allowed to remove triggers and have it expressed as code, that can be tested and refactored.

What were the goal of this exercise?

  • Simplify application maintenance
  • Easier refactoring
  • Capturing application behaviour in application, and not database
7/12/2008

How Did I Get Started In Software Development?

JP called me out, so here I am, trying to travel back in time to recall how the heck I ended up coding.

How old were you when you first started in programming?

I was 16 years old when I touched computer for the first time with intension of more than just playing a video game. Not that I was a big gamer before that - I was not. I got my 1st computer when I was 16.

How did you get started in programming?

By accident, accident that took place at school. I had a subject called "Programming", and was doing well on everything, besides this one. My mom met the teacher who advised to purchase a computer for me, so I could practice more and get better grades in programming. So my mom did. Anticipated results were confirmed, partially. I improved my marks on programming significantly, abandoning the rest of the subjects behind. Got myself into programing graphics, demos, 3D. And that probably what can be tagged as the source of the decease.

What was your first programming language?

Pascal.

What was the first real program you wrote?

A demo for the local demo competition my friend and I put together. This was the first time I actually exposed what I was into publicly, letting the word "geek" stick to my first name, partially replacing the last name.

What languages have you used since you started programming?

Hebrew, English, Russian... ah, programming languages!

Pascal, Delphi, C, C++, Java, JavaScript, DHTML, Assembly x86, T-SQL, VB6, VB.NET, C#.

What was your first professional programming gig?

Back in 2001, putting together the theory and the practicality at my first workplace.

If you knew then what you know now, would you have started programming?

Yes, yes, and yes. I would not change a thing in a way it started (at what age and circumstances), but I would definitely pay more attention to the wise advices I disposed through so many years, especially in the begriming.

If there is one thing you learned along the way that you would tell new developers, what would it be?

Stick to what you believe into, go forward to achieve your targets, but be careful not to become an ego-bully. Perfect yourself as a developer, knowing that perfect does not exist in nature, and yet not loosing your dream of doing better then you've done so far. Remember that as developers we use computers to accomplish our mission, but worked, working, and will work with real human beings, that are not computers.

What's the most fun you've ever had programming?

Being able to affect other developers. The power of satisfaction from being able to positively affect other developers around, constantly improve myself to allow surrounding do the same - is amazing. Finding friends that are also developers and as crazy about things that we do as I am, is the most fun, knowing that you are not the only one, and if locked up in an institution, you will your good friends with ya.

Who am I calling out?

Terry Thibodeau

Karl Seguin

Glen Little

7/3/2008

Visual Studio Floating Windows and Keyboard Shortcuts

Visual Studio floating windows are not playing nicely with keyboard shortcuts. If you only using a keyboard, and want to be able to navigate around without constantly getting destructed by a mice, it's ok. But floating windows are impossible to close without touching a mouse. At least I am not familiar with a way to do it. Imagine you could do something like this - press ALT-Space on floating window and... close!

image

Wouldn't it be nice? :)

7/2/2008

MbUnit 2.4 PlugIn for ReSharper 4.0

Albert Weinert has release an update to his plugin to allow execution of R# 4.0 from within Visual Studio .NET 2005 / 2008. The only Unit Testing framework supported by R# 4.0 out of box is NUnit, so this is a useful plugin for those who prefer MbUnit to NUnit.

I recall that one of the final features for R# 4.0 was planned to provide out-of-box plugins and support for several Unit Testing frameworks. Wonder what happened to that plan.

6/27/2008

IDs to Objects

A few months ago I blogged about Domain Objects vs. Primitive Types. Back then it felt right to me to transform a primitive type, like a Guid that represented, to an Organization domain object. Unfortunately at that time I was not educated enough to know that this is a common idiom in among many object designers. Apparently it is. Craig Larman writes it nicely in his book (in my case Organization is what Craig references to as a Customer):

Why bother? Having a true Customer object that encapsulates a set of information about the customer, and which can have behaviour , frequently becomes beneficial and flexible as the design grows, even if the designer does not originally perceive a need for a true object and thought instead  that a plain number of ID would be sufficient.

The other important note is when this transformation is taking place - when an ID or a Key leaves the UI layer and gets to the Domain Layer.

6/19/2008

Have Honest Opinion

It is very hard to provide an honest opinion when you are involved in a situation. I found it always difficult for myself and admired people of being able to do it, lifting themselves from emotional attachments to the matter.

I am a big fan (if not huge) of the whole Google Apps platform. I use heavily Gmail, rely a lot on Google Calendar, abandoned Excel for simple-to-average stuff and went with Google spreadsheets. I used Google Maps, because it was better than Microsoft's competitive version of the product. Till I had a chance to re-evaluate it again. This time around Microsoft has produces a better result. Microsoft Live Maps gives me more than Google Maps does (weird even to think it, not mentioning writing it :).

What made the difference? The level of details, an option of having a closer look, real images. Anyway, I am not using Live Maps.

6/16/2008

Command-Query Separate Principle

A few days ago read in Larman's book about Command-Query Separation Principle. Funny to mention  that I heard about the concept many times ago, but this is the only source that stated it as a principle. And it makes total sense once you evaluate all the pros and cons of the idea.

What's the principle? Simple. There are two kinds of messages to objects:

  • Commands - ones that are affecting the state of the object
  • Queries - ones that are querying an object for its' state without affecting its' state at all

A Command message would be "void Calculate()" or "void Add(double value)". Command message never returns a value, and that's for clear separation of the messages and easier maintenance of the object state (i.e. no surprises). A Query message would be what Command isn't "int GetValue()" or "IsVisible()".

One exception the author brought up was internal/private messages that are not a part of the interface, and therefore can violate the principle - I guess this is a matter of personal preference.

An example is an implementation of a Die (for a monopoly game) modified by myself.

    public interface IDie 
    {
        void Roll();
        int GetFaceValue();
    }
    
    public class Die : IDie
    {
        private int faceValue;
        private Random rand = new Random();
        
        public void Roll()
        {
            faceValue = rand.Next(6) + 1;
        }
        
        public int GetFaceValue()
        {
            return faceValue;
        }
    }

I added the interface on purpose, to have DbC, where implementation doesn't matter that much, because the contract is expressing well enough the intension of how to use an implementer of  an IDie. Thanks to the CQS Principle it becomes crystal clear. It is easy to determine a value of a die, and there's no surprises when a die is queries for it's value.

Now imagine a system with a significant number of components that violate this principle versus a system where components follow it. Can you imagine the difference?

6/15/2008

3 Years

Today is 3 years since I started working with the company I work today. It's being a long journey from figuring out what I want, till realizing what I am and need to be. The team has accepted all of my wildest ideas about the code and was very tolerant to the fact that I cannot wait to get something done. We've made a long way.

Besides improving as a software developer, I also realized a few bitter realities - it doesn't matter how good I am, still need to strive to be better. Besides the excellence in code, there must be a proficiency in human relationships. The code is not only about a single developer level, but about team level, because if you are the only one who can have fun with it, it is no longer fun.

Lessons are good, but I have to look forward and setup certain goals for myself, what do I want to achieve the next year? A lot.

  • I want the team to get to the point where I am right now, and I can do more for that
  • I want to have more fun while working, because without it work is useless
  • I want be more influencing people, help them realize themselves better, without getting into conflicts
  • I want to improve a lot myself, and by doing that to show, that you can achieve if you want to

Some of my targets will change or get updated, but the core set of goals will remain.

A lot ahead, I better start moving towards it.

6/12/2008

Code Smell vs. Code Stench

Interesting difference I picked up from a book this morning - code smell vs. code stench.

Code smell might indicate there's a problem in code that requires refactoring, but a closer evaluation might prove the smell is false alarm.

Code stench is an obviously bad/poor code that has to be refactored.

From now on I will be more accurate on describing the code issues :)

Google Shortcut Keys - Awesome

For all keyboard junkies out there - if you are also hooked on Google products (GMail, Reader, Calendar, etc), don't miss the option of using GMail with keyboard shortcuts. The are awesome. I loved the navigation shortcut (combination of pressing first G and then another key, neat).

To enable keyboard shortcuts, you will have to go to the settings under you GMail account and check off the option to enable it.

6/11/2008

Two Loosely Coupled Code - Part 2

In the

I raised the question of "Too loosely coupled design". There's a lot to discuss about it, and I am not going more time on it, except showing one more sample that IMHO shows the benefits and outcomes of the principle being applies, or consequences of not doing so.

Table 1

namespace Local.ADL.Home
{
  public class HomePresenter : IPresenter
  {
    private readonly IHomeModel model;
    private readonly IHomeView view;

    public HomePresenter(IHomeView view): 
                        this(view, new HomeModel()){}

    public HomePresenter(IHomeView view, IHomeModel model)
    {
      this.view = view;
      this.model = model;
    }

    public void Initialize()
    {
      view.Load += View_OnLoad;
    }

    private void View_OnLoad(object sender, EventArgs e)
    {
      if (!view.IsPostBack)
      {
        view.AssignInitialData(model.IsUserMemberOfPlanAOrPlanB(),
                model.CanShowSomething());
      }
    }
  }
}

Table 2

namespace Local.ADL.Home
{
  public class HomeModel : IHomeModel
  {
    public bool IsUserMemberOfPlanAOrPlanB()
    {
      return UserSession.IsPlanAorB;
    }

    public bool CanShowSomething()
    {
      return UserSession.ShouldSeeSomething;
    }
  }
}

Q: Can HomePresenter be tested based on the code in Table 1?

A: Yes. It has a parameterized constructor that accepts all dependencies for HomePresenter as contracts (interfaces) without knowing or carrying who are the real components that implement those contracts. Loosely coupled code, where we depend upon abstraction and not concrete implementation.

Q: Does HomePresenter is loosely coupled at run-time?

A: No. It has a direct dependency on HomeModel class. This is a tight coupling, meaning that anywhere in the code we used this type of coupling, we made HomeModel “visible” for HomePresenter, i.e. we violated the principle of depending upon abstraction and not concrete implementation. What would be a solution? Dependency Injection Principle with a standard container (lets call it DependencyResolver). Using this simple principle would change the code to be something similar to the code in Table 3. Now HomePresenter is loosely coupled to the implementer of the IHomeModel contract. Some configuration file / startup code will determine who is the actual implementer at run-time. Testing is still possible.

Table 3

namespace Local.ADL.Home
{
  public class HomePresenter : IPresenter
  {
    private readonly IHomeModel model;
    private readonly IHomeView view;

    public HomePresenter(IHomeView view): 
       this(view, DependencyResolver.GetImplementerOf(IHomeModel)){}

    public HomePresenter(IHomeView view, IHomeModel model)
    {
      this.view = view;
      this.model = model;
    }

    // ...

Q: Can HomeModel be tested based on the code in Table 2?

A: No. It is tightly coupled to the UserSession, which in its’ case is a static class and cannot be mocked / faked / taken out as a component that is not required to be tested at this moment.

To solve it:

  • UserSession has to be implementer of a contract, lets call it IUserSession
  • The implementer of IUserSession has to be supplied / injected as a dependency during construction time either directly or through container, similar to the example in HomePresenter code in Table 3
4/21/2008

Whiteboard vs. Excel - Part 2

I have posted before about the subject, and there was a strong hold on both sides (for and against). Yesterday I run into a blog that mentioned a software called Mingle 2.0 - obviously not the first version according to the name, but I have never heard of it before, so it might be a naming game (all the Web 2.0 thing) - who knows? And probably someone knows. If you a successful survivor of the software or have  a few words to drop, leave your comment after the beep.

Beeeeep.

What About ALT.NET Calgary Group?

We have some very talented and blade sharp people here. So why can't we start ALT.NET Calgary local group? This would definitely promote excellent ideas around, enrich our dev community, put more stress on quality, agility, and much more. Feel free to contact me if interested.

PS: I am quite inspired by what is going on right now at the ALT.NET conference. Wish would be there...

The Matrix

Inspired by people like JP. Thank you.

The Matrix has you...

- Ever have that feeling where you're not sure if you're awake or dreaming?

- How did you do that?

- Right now, all I can tell you... is that you're in danger. They're watching you, Neo.

- Who is?

- Please just listen. I know why you're here, Neo. I know what you've been doing. I know why you hardly sleep... why you live alone and why, night after night... you sit at your computer. You're looking for him. I know, because I was once looking for the same thing. And when he found me... he told me I wasn't really looking for him...

- ...I was looking for an answer. It's the question that drives us, Neo.

- It's the question that brought you here. You know the question... just as I did.

- What is the Matrix?

So what is the Matrix? Matrix is the existing software culture that has us all playing by it's rules. Matrix is the classic waterfall with the big fat design up front, if you wish. Matrix is the culture of lonely stars "ruling" the code-world, or at least the imaginary worlds they create.

What is the question? Question is what doesn't let you fit nicely into the Matrix, causing discomfort and feeling of bad taste in your mouth, while you trying to digest it. Question is your passion to something that can be better, and you know that Matrix is not it.

- The answer is out there, Neo. It's looking for you. And it will find you... if you want it to.

The answer is not single, these are multiple answers. Answers are Alternatives. You won't have answers, until you embrace alternatives. You won't have answers, until you try the alternatives. You won't have answers, until you are honest enough with yourself and make the decision.

Bzzz - bzzz - bzzz - bzzzz

-Oh shit!

Shit - that's how reality looks like when you wake up to it in the morning, with a great tune of the buzzing clock. But is it? You know this is not the reality you want to leave, you know that you can do more and better. You know that the answers will help you to get where you want to be. All you need to do is answer the question(s). Or at least try to. Yes, you will try to get the answer to your question(s) and by that change the stinky reality. And right then the reality kicks into the next gear. Reverse.

- You believe that you are special, that the rules do not apply to you. Obviously, you are mistaken. This is one of the top software companies in the world... because employees understand they are part of a whole.

And back you are to your beloved desk and sad reality.

- Hello, Neo. Do you know who this is?

- Morpheus.

- Yes. I don't know if you're ready to see what I want to show you. But unfortunately, you and I have run out of time.

We all need such a call. A wake up call. A call that will make it clear that something has to change in how you do things. The way you think, the way you work. A wake up call to realize that time is not your ally, but the worse enemy, and if you don't act, answers will remain unrevealed.

- Please, Neo, you have to trust me.

- Why?

- Because you have been down there. You know that road. You know exactly where it ends. And I know that's not where you want to be.

When the time comes to make some painful decisions, we chicken out. We normally do, because it's different, it's new, it's unknown, it doesn't feel familiar and the comfort is gone. Unknown feels so heavy when possession of already accumulated knowledge makes you feel so great about yourself. But deep inside you know that that road is not for you, there's nothing left for you. You have traveled that road and it's not the one that takes you to the answers.

- Let me give you one piece of advice. Be honest.

Giving and taking advices is easy. Following those is tougher. Be honest with yourself, your skills, you abilities. Am I as good as I want to be thought of? Am I adding value by what I do? Am I making any difference, or just doing the same old thing is some other trivial way? Am I honest about answering the questions I face? Honesty is the key to loose the unnecessary fears that are roadblocks to the answers you are looking for. At least it serves as a good kick off point.

- I imagine... that right now you're feeling a bit like Alice... tumbling down the rabbit hole?

- You could say that.

- I can see it in your eyes.

- You have the look of a man who accepts what he sees... because he's expecting to wake up. Ironically, this is not far from the truth.

Find the people who will see what you going through in your eyes, wise people who can sense what you going through to show you a hint to what you are looking for.

- It is the world that has been pulled over your eyes... to blind you from the truth.

- What truth?

- That you are a slave. Like everyone else, you were born into bondage... born into a prison that you cannot smell or taste or touch. A prison for your mind. This is your last chance. After this, there is no turning back. You take the blue pill the story ends, you wake up in your bed and believe whatever you want to believe. You take the red pill, you stay in Wonderland, and I show you how deep the rabbit hole goes.

Remember... all I'm offering is the truth. Nothing more.

The blue pill for me is falling back into old habits. Waterfall, BDUFs, cubical, DB driven designs. The red pill for me is Agile, TDD, open communication, team, openness. I choose the red pill not only to know how deep the rabbit hole goes, but also to test my abilities to go even deeper. I choose the red pill, because I prefer bitter truth to sweeter illusion. I choose the red pill because I want the truth. And my truth is that I still have the dream and on my way of achieving it.

Don't abandon your dream. Don't live in Matrix.

4/10/2008

Changes

After a long time I had the book sitting idle, finally I had a chance to get my hands image on it - Who Moved My Cheese. A very nice, fairy tale kind-of book teaching how to cope with changes. I loved it, especially it's nice to read if you are trying to wrap around the agility concept.

Be ready for changes, be ready to change. Be ready for things become and stay dynamic. You have to be dynamic. Don't be a littlepeople, with a two complicated brain analysis to adopt to changes, be quick and pragmatic, adopt and period. Nice book, worth reading.

PS: I think I will introduce my son to this nice story. His brain is much better of adopting then mine :)

4/9/2008

Pair-Programming, Keyboard, and Mice

While pairing today with on of the developers from our team, we decided not to let the mice to destruct us, and unplugged it. That was awesome - within seconds we diagnosed ourselves with a mouse-have-to-touch addiction symptom. Every single moment a hand was reaching to the sacred location two things happened:

  1. The mouse wasn't working
  2. The brain was realizing that there's an alternative - keyboard

It probably took an hour to digest the great loss, but we started to rely on R# and keyboard shortcuts to do the job. I can definitely see the difference between the start and the finish.

The other challenge is how to practice something similar with a person who is pairing remotely - you can ask to disconnect the mice and drop it to the bin, but it's not always working. A typical reply would be "Sure! What for? I simply won't touch it". And 3 seconds after that you see the sneaky mouse making it's way from one corner of the screen to the opposite one (or worse, expressing the thoughts of the confused 'master', while trying to thing what is needed to be done).

So I can't unplug the beast, can I then mute it? Wow, that would be nice, an application to temporarily disable mouse. What do you think? (This  is where I solicit for a utility name).

Confession: I am not using mouse for a while while developing, and the whole purpose of the experiment was to prove to my team mates that they can do wit no problems at all.

Reminds me words of Morpheus from Matrix movie in context to the importance of the mice to work: "Do you think it's the air that you breath? Hmmm. Interesting...."

3/10/2008

Training Session Observation

It is nice once in a while to get back to the course or training session you took and make sure that you haven't wasted your time for nothing. This is not about ego, this is about making sure that what ever you know today will be absolutely no enough tomorrow and constantly remind yourself this basic law of software development.

I am lucky to TA at JP's Nothing But .NET boot camp. Unlike MSDN events, NBDN is a whole different story. If you heard of it and were hesitating, or doubting if it is for you at all - my answer would be short - if you are hungry for knowledge and always looking how to improve yourself - get it.

It takes a little to generate a big change, a boot camp like this is that little that you can do to change how you work and what you produce. Check it out!

2/29/2008

Pair Programming And Sharing Knowledge

Pair programming is a proven technique for sharing knowledge among team members and teams. Benefits of that are felt after relatively a short period of time, boosting not just the productivity, but self-confidence of the developers (which is playing an important role even though is not admitted), and most of all, improving the maintainability of the code when it comes later. And it comes. It always comes.

But I would like to review additional alternatives to the knowledge sharing with team members (both direct team members, and those that are a part of another teams that might not come into direct contact with what your team is doing). What are the ways to share the knowledge?

From my personal experience, group lectures are in-effective. People are coming into those, hating it, and taking almost nothing valuable as they leave. Code camps are excellent, but the majority of the people who are attending those are doing it out of their own curiosity, enthusiasm, or just will to be better developer.

What I was doing in the company I work for, is a short (30-45 minutes) meetings once a week or two, hands on code. And the presenter was elected at the end to present his/her topic. IMHO this was working, but others may disagree. I think this was working for the developers who believed that it's not just a task of presenting, but a responsibility not to waste others time and let them learn from others what they would not learn on their own due to the lack of time or opportunity.

So what are you practicing if at all?

2/26/2008

Sucks To Work Blind

image

I was holding off using R# when it's not even in an EAP mode. But today I have had it. Uninstalled R# 3.1 for Visual Studio .NET 2008 and went to R# 4 nightly build.

2/22/2008

Know Your Friends Well, Know Your Enemies Better

Long time ago I had to deal with a case where the famous ViewState generated by WebForms was quiet heavy. This post is not going to wine about how bad ViewState is for the environment. This post is to show that even working with something big and nasty such as web forms, you still have to give a thought what are you trying to do and what is out there that can help you to accomplish the mission.

Before getting into the "solution" (well, it is a solution, but kind-of stinky if you are asking me), I would really recommend the post about what is ViewState and it's influence on your nervous system.

So what is solution - not to use ViewState :) Week solution.

Spike and invent something - bad idea. The wheel in already invented.

Spike on WebForms implementation and learning - that's the one.

 

First we need to look at the "container" of the ViewState which is nothing but a Page. This is where one of my favourite tools for reflection is making its' big entrance - Reflector. Looking at the page, you shall see that a page has an interesting getter called "PageStatePersister".

 Page class using reflector

Digging deeper provides an insight into the intension of this property:

   1:  protected virtual PageStatePersister PageStatePersister
   2:  {
   3:      get
   4:      {
   5:          if (this._persister == null)
   6:          {
   7:              PageAdapter pageAdapter = this.PageAdapter;
   8:              if (pageAdapter != null)
   9:              {
  10:                  this._persister = pageAdapter.GetStatePersister();
  11:              }
  12:              if (this._persister == null)
  13:              {
  14:                  this._persister = 
  15:                      new HiddenFieldPageStatePersister(this);
  16:              }
  17:          }
  18:          return this._persister;
  19:      }
  20:  }

A few interesting things in particular we can learn from the code:

  1. The default state persister fro ANY page is a HiddenFieldPagePersister, the one that generates a hidden field with all the gibberish
  2. A page can have an Adapter that could potentially redefine what's the default persister for pages (bookmark this concept for a while, for people like myself, write it down on a piece of paper with a title "review this later")
  3. Regardless of the fact what persister is going to be used, this is a Template Method that acts as a Factory to return back an object that has was derived from an abstract PageStatePersist class

What a world of opportunities in such a limited world of ViewState! Let's use reflection to find out what are the possibilities. And the winners are:

PageStatePersist class 

Not that much of options, but hey, we can have an option of keeping it at "home" on the server side, rather than sending to the client EVERY-SINGLE-ROUNDTRIP!

There are a few options:

  1. Act on a page level and override the Templated Method to return an instance of SessionPageStatePersister rather than HiddenFieldPageStatePersiter
  2. Create an adapter for the entire application
  3. Choose between option 1 or 2 with a custom persister class, inherited from abstract PageStatePersist

Option 3 is for your wild and kinky imagination, option 1 is too trivial, option 2 is what I would like to expand a bit.

So we want to reconfigure the entire web application for a different persister (Session one for the application that has lots of stuff in ViewState, and should produce a slim HTML). Adding a folder App_Browsers allows us to register different controls adapters. Page is a control as well, see for yourself:

image

In this folder, we can specify adapters per browser, or all of them (ahh, my old days of WAP development with Mobile ASP.NET are bubbling up, causing me a horror moment). Something like BrowserFile.browser file should do it - use VS.NET add new item option to add a .browser file. Then register an adapter for a page. The adapter code would be simple as this:

   1:  using System.Web.UI.Adapters;
   2:  using System.Web.UI;
   3:   
   4:  public class SesionPageStateAdapter : PageAdapter
   5:  {
   6:    public override PageStatePersister GetStatePersister()
   7:    {
   8:      return new SessionPageStatePersister(this.Page);
   9:    }
  10:  }

.browser file would be a mapping like this:

   1:  <browsers>
   2:   <browser refID="Default">
   3:     <controlAdapters>
   4:        <adapter controlType="System.Web.UI.Page" 
   5:                 adapterType="SesionPageStateAdapter" />
   6:      </controlAdapters>
   7:     </browser>
   8:  </browsers>

Unfortunately it will not remove the ViewState completely, but it will definitely minimize it. Sometime several dozens of KB can be prevented from going back and forth. Also keep in mind that ControlState (from ASP.NET 2.0 and later) is possible contributing, and that one is not disableable.

Hopefully this helps to those who are in pain of watching hundreds of Kilobytes traveling there, taking more "page weight" than the page content itself.

2/20/2008

Understanding IoC Container - Part 2

I try to lower expectations in order not to be disappointed, but in this case I was asked by several individuals to address the fact that IoC container power is in the ability to "hook" implementer with the contract through an external file, leaving application code unaware of the actual implementer till the run-time, having no reference to implementers' assembly or whatsoever. I am going to expand the sample from the part 1 post to achieve that goal in a couple of day.

2/16/2008

Understanding IoC Container

In a multi layered application architecture, loosely coupled code is more than a important. It's the basic which can either help the entire project progress, or drive it down the slope to the end (in the bad meaning of the word). One of the basics to keep coupling as low as possible is Inversion of Control (IoC) container.

I will try to show how to put in place a simple version of IoC container to allow loosely coupled design. The solution will contain several projects to emulate a layered application as much as possible. The choice of console application is only driven by intent to keep it as simple as possible.

In our application we do basic logging at all layers. Logger that does it is following the next contract:

  public interface ILogger
  {
    void Log(string message);
  }

Lets assume that the initial version of logger is implemented as a simple Console logger:

  public class ConsoleLogger : ILogger
  {
    public void Log(string message)
    {
      System.Console.WriteLine(message);
    }
  }

Now lets look what the layered structure looks like. The lowest layer in the stack is going to be Core. This one will contain the interfaces (such as ILogger for instance) all other layers have to consume. This is a sort of tight coupling, but it is not bad as upper layers will depend on abstraction and not concrete implementation (DIP).

ioc_layered_structure

AssemblyOne, Two, Three, and others are all potential layers you could have (and I am not necessarily insisting on having them - there should be a rational limit). ConsoleApp is the top layer that represent the application. This could be easily a Windows application or a web application.

To spice up our life, we have to implement a gadget in AssemblyOne that will follow a certain contract (IGadget) and each operation defined by the contract, has to be logged when implementation is invoked. The contract is:

  public interface IGadget
  {
    void TurnOn();
    void TurnOff();
  }

Now the implementation of the Gadget will be quiet simple:

   1:  using Core;
   2:   
   3:  namespace AssemblyOne
   4:  {
   5:    public class Gadget : IGadget
   6:    {
   7:      private readonly ILogger logger;
   8:   
   9:      public Gadget(ILogger logger)
  10:      {
  11:        this.logger = logger;
  12:      }
  13:   
  14:      // Default constructor will be discussed a bit later 
  15:      // public Gadget() {}
  16:   
  17:      public void TurnOn()
  18:      {
  19:        logger.Log("TurnOn");
  20:      }
  21:   
  22:      public void TurnOff()
  23:      {
  24:        logger.Log("TurnOff");
  25:      }
  26:    }
  27:  }

The program in the upper (ConsoleApp) layer will look this way:

   1:  using System;
   2:  using AssemblyOne;
   3:  using Core;
   4:   
   5:  namespace ConsoleApp
   6:  {
   7:    internal class Program
   8:    {
   9:      private static void Main()
  10:      {
  11:        AppCode();
  12:   
  13:        Console.WriteLine("done.");
  14:        Console.ReadLine();
  15:      }
  16:   
  17:      private static void AppCode()
  18:      {
  19:        ConsoleLogger logger = new ConsoleLogger();
  20:        Gadget gadget = new Gadget(logger);
  21:        gadget.TurnOn();
  22:        gadget.TurnOff();
  23:      }
  24:    }
  25:  }

AppCode method (lines 19-22) is what we are interested in. A few question can be raised at this point:

  1. Why logger is of type ConsoleLogger and not ILogger? Isn't this wrong?
  2. Why gadget is of type Gadget and not IGadget? Same smell?
  3. What if we need to move logger implementer to a different layer than the ConsoleApp?

These are all excellent questions. The first two are definetely a bad smell. Why? Well, because we should be really sticking to what contracts were obligating implementers, and not be even able to use the "extras" provided by contract implementers "outside" of the contract. This will eliminate any chance that an "undocumented" by contract method will extinct from existing, causing our client code to break. The third question is the one that shows that current design is not going to work - current ILogger implementer is located in ConsoleApp layer and we have to pass it as a dependency into gadget. But what if we introduce another implementation of ILogger, like XML logger, and it will live in another layer, AssemblyTwo? And what if we want to be able to create gadget without specifying logger, relying on a default one? This is where IoC container would help.

The idea behind container is simple: lower layer provides an option of registering a contract implementer, and later, retrieve that contract implementer instance, by just using the contract type. Expressing this in code would look like the next snippet:

namespace Core.IoC
{
  public interface IContainer
  {
    // register contract implementer
    void AddImplementerFor<ContractType>(Type implementer);
    // retrieve contract implementer
    ContractType GetImplementerOf<ContractType>();
  }
}

Implementation of this contract is a subject to a separate discussion. To keep it simple, I have decided to use the simplest way out there:

   1:  using System;
   2:  using System.Collections.Generic;
   3:   
   4:  namespace Core.IoC
   5:  {
   6:    public class Container : IContainer
   7:    {
   8:      public static readonly IContainer Instance = new Container();
   9:   
  10:   
  11:      private readonly Dictionary<Type, Type> container;
  12:   
  13:      private Container()
  14:      {
  15:        container = new Dictionary<Type, Type>();
  16:      }
  17:   
  18:      public void AddImplementerFor<ContractType>(Type implementer)
  19:      {
  20:        container.Add(typeof(ContractType), implementer);
  21:      }
  22:   
  23:      public ContractType GetImplementerOf<ContractType>()
  24:      {
  25:        return 
  (ContractType)Activator.CreateInstance(container[typeof (ContractType)]);
  26:      }
  27:    }
  28:  }

Yes, the core secret is in Activator class, provided by .NET framework. No magic.

With this in hand, we can start using container all other the place, breaking the dangerous coupling. First thing first, registering contracts and their implementers for the application. This will change how we start our application:

   1:  using System;
   2:  using AssemblyOne;
   3:  using Core;
   4:  using Core.IoC;
   5:   
   6:  namespace ConsoleApp
   7:  {
   8:    internal class Program
   9:    {
  10:      private static void Main()
  11:      {
  12:        ApplicationStartup();
  13:   
  14:        AppCode();
  15:   
  16:        Console.WriteLine("done.");
  17:        Console.ReadLine();
  18:      }
  19:   
  20:      private static void ApplicationStartup()
  21:      {
  22:        Container.Instance.AddImplementerFor<ILogger>(typeof(
                                                           ConsoleLogger));
  23:        Container.Instance.AddImplementerFor<IGadget>(typeof(Gadget));
  24:      }
  25:   
  26:      private static void AppCode()
  27:      {
  28:        IGadget gadget = 
                            Container.Instance.GetImplementerOf<IGadget>();
  29:        gadget.TurnOn();
  30:        gadget.TurnOff();
  31:      }
  32:    }
  33:  }

Line 12 introduces a new (quiet old actually) concept - application startup point. In web application something like Application_Start in Global.asax would be an equivevalent. What it does is teaching the container about contracts, and who are the implementers. That way, we can get an instance of an IGadget without worrying who implements it (line 28). Also we don't need to directly inject the logger dependency, due to the fact that gadget can query for the default logger through the container. Updated logger looks like this:

   1:  using Core;
   2:  using Core.IoC;
   3:   
   4:  namespace AssemblyOne
   5:  {
   6:    public class Gadget : IGadget
   7:    {
   8:      private readonly ILogger logger;
   9:   
  10:      public Gadget(ILogger logger)
  11:      {
  12:        this.logger = logger;
  13:      }
  14:   
  15:      public Gadget() : 
                    this(Container.Instance.GetImplementerOf<ILogger>()) {}
  16:   
  17:      public void TurnOn()
  18:      {
  19:        logger.Log("TurnOn");
  20:      }
  21:   
  22:      public void TurnOff()
  23:      {
  24:        logger.Log("TurnOff");
  25:      }
  26:    }
  27:  }

Line 15 defines a default constructor that leverages container to get the default implementation of logger.

Now we will substitute the default logger by another implementer, from another assembly (AssemblyTwo) that logs information into an XML file:

   1:  using System;
   2:  using System.IO;
   3:  using System.Xml;
   4:  using Core;
   5:   
   6:  namespace AssemblyTwo
   7:  {
   8:    public class XmlLogger : ILogger
   9:    {
  10:      private readonly string fileName;
  11:   
  12:      public XmlLogger() : this("log.xml")
  13:      {
  14:      }
  15:   
  16:      public XmlLogger(string fileName)
  17:      {
  18:        this.fileName = fileName;
  19:      }
  20:   
  21:      public void Log(string message)
  22:      {
  23:        XmlDocument document = new XmlDocument();
  24:        string filePath = Path.GetFullPath(fileName);
  25:        CreateFileIfDoesntExist(filePath);
  26:        document.Load(filePath);
  27:        XmlElement root = document.DocumentElement;
  28:        XmlElement element = document.CreateElement("log");
  29:        element.SetAttribute("timestamp", 
                         DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff"));
  30:        element.InnerText = message;
  31:        root.AppendChild(element);
  32:        document.Save(fileName);
  33:      }
  34:   
  35:      private void CreateFileIfDoesntExist(string filePath)
  36:      {
  37:        if (!File.Exists(filePath))
  38:        {
  39:          XmlWriter writer = XmlTextWriter.Create(fileName);
  40:          writer.WriteProcessingInstruction("xml", 
                                       "version='1.0' encoding='UTF-8'");
  41:          writer.WriteStartElement("logs");
  42:          writer.Close();
  43:        }
  44:      }
  45:    }
  46:  }

The adjustment has to be done to the startup method to register the new implementer in the container:

    private static void ApplicationStartup()
    {
      Container.Instance.AddImplementerFor<ILogger>(typeof(XmlLogger));
      Container.Instance.AddImplementerFor<IGadget>(typeof(Gadget));
    }

Now the entire system uses XML logger as a default logger:

ioc_layered_structure_container

There is a scenario when contract implementer is in an assembly that should not be referenced from the code (due to the fact that it is just not available during the development time)? Then something like an external file for container configuration can/should be used. We will have to specify the assembly name as well, so the activator would be able through the reflection to invoke constructor.

Bottom line - this is far from being perfect, but it was not intended to do the heavy lifting (though could be used to do IoC container work). My recommendation would be to understand what power it gives you and take one of the existing containers such as Windsor, Spring.NET, StructureMap, etc.

...hey, what's up with the log there? Was it working at all? See for yourself, get the code

.

<?xml version="1.0" encoding="UTF-8"?>
<logs>
  <log timestamp="2008-02-14 22:53:10.014">TurnOn</log>
  <log timestamp="2008-02-14 22:53:10.060">TurnOff</log>
</logs>

2/4/2008

Immutable Collection (Secure Proxy Pattern) Example

Mr. Mo has wrote a nice post about securing collection and turning it into an immutable object. I am adding my 20 cents by reminding a great example JP Boodhoo has showed during his "Nothin But .NET" training session, leveraging ReadOnlyCollection<T> class to make a collection immutable.