July 2008 - Posts

Logging is the process in which trees are cut down for forest management andimage timber. Logging is controversial due to its potential environmental and aesthetic impacts. 

I am going to talk about other one, the one that is vital, helpful, and has positive impacts. Software logging.

Hosted projects are easier in terms of debugging and tracing issues - you have got all the control in case you are the host. Though in some cases even the fact that you hosting the application does not help. Then troubleshooting becomes painful if not impossible.

This is where Diagnostics Trace class was helpful to provide the data that would help to resolve an issue or two. But for the logging part - it wasn't the best tool out there. So I have decided to have a look at what others are using, and quite a dominant candidate was log4net OSS component. Any objections?

I'd like to drop a few word for the book was lucky to read lately - Fearless Change: Patterns for Introducing New Ideas.  Authors of the book have succeeded to capture ways to apply changes in amazingly accurate way. Written as a pattern book with orientation for software development (and not only) this book makes a perfect read for those who are willing to make changes and affect others.

Firefighters are not analyzing the situation, they are taking several plans to consider leaving the simplest and the least harmful to be executed. Can be this applied anywhere? No. When you have stressful times in software development you need to enrich your knowledge and learn about the problem. Doesn't mean to put on hold the development. Neither it means to implement the firemen approach and forget about it. It means take out the fire and learn how to avoid fires in the future by implementing the proper solution when you can.

Note on that: I teach myself to respond and not to react. Reacting is more reflex style, where response is more weighted and analyzed answer. That way a dialog can take place that leads to a quicker decision on how to take the fire out, and not a spontaneous acts driven by emotions that lead to nothing, but fire swallowing more than it should have in first place.

So today I was challenged. Challenged to talk about my achievements at the company I work for. Why is it a challenge? Simply because I don't like to brag about my personal achievements when know how much I still have to achieve. But in this case this is different, as I would like to have a chance to look back and review what are the achievements I managed to generate in the company (Note: compensations are not linked to this :).

Three years ago, joining the company, I was going to be a web developer with database background. I found myself in a code base entirely .NET 1.1 with VB.NET roots taking place in classic ASP with VB script, a lot looking like a procedural recreation in a object oriented environment, doing a lot of things I've never done before. Being a C# developer mostly, I set a technical mission to convert the whole company to C#. That conversion took a while along with porting to .NET 2.0. We got there.

Components where the second step I took in that direction. Since we are dealing with web UI and it has quite a limited amount of standard UI elements, I pushed towards innovating and creating new web controls that would allow us slicker UI and UX along with re-usability. This had a price. Not sure if I managed to convince anyone to create those, but developers do use it heavily on the daily basis and raise issues and concerns that push all of us as a development team to think through and design better. This probably leads to another achievement - a move from innovator to early adopter.

I used to be a cutting edge innovator. Not the best thing if you ask me. Jumping into a new technology without being concerned about business side is too risky and frankly speaking doesn't give you any credibility in eyes of other developers/management. So I changed to become an early adopter instead, i.e. through my personal passion and example show and prove that certain things I believe in are worth adopting.

As my knowledge about what we were trying to achieve was expanding, I started to work on the idea of an internal framework. A few leaps and a lot of bugs with assistance from all of our developers this became a reality. Nowadays most of the applications we build are based on it.  

The next major influence I had was the layered design. No, I haven't re-invented the wheel, but I showed the way. And I pushed it all the way till we've got it. This was a great experience with the whole team. Just by doing that we opened so many worm-cans, there was enough for a while to keep us busy. Now looking back it makes me feel good to realize that the team didn't kill me for doing it :)

Another step in the right direction was to get away from the standard plain ADO.NET - a step I am still taking. Working with meaningful objects rather than with object-representation of tables and views was more appealing to me. So I initiated the migration. We ended up having our internally developed Entities Framework. This step allowed us to realize something I was about to learn - back to the core principles.

Still hungry for better results I pushed our boundaries to go from plain vanilla web forms to an MVP implementation. Slowly it caught up. Today I think there's no developer on the team that does not realize the importance and effectiveness of simple core principle - separation of concerns. Talking about core...

Gladly I can state that the biggest achievement throughout these 3 years was the realization that we didn't do proper object-oriented code. I lucked core principles, better understanding of patterns, refactoring. This is where I started to look for alternative, search for the answers. This is the point in time where I introduced the management and the developers to the design patterns, principles, agile methodology (pushing this was an interesting experience we are just starting to experience). Self awareness as professional developers started to raise. I feel definitely satisfied about that.

This could go on for a while, but I don't really want to keep going. No point. Rather I would like to re-cap the most important achievement the team allowed me to put in place:

  • Pushing the professional boundaries
  • Turning to better object oriented development
  • Accent on core principles, patterns and idioms
  • Move towards the agility (even we are not, the bug is there)
  • Awareness of constant improvement required by each one of us

To summarize this - we've went a long way and a lot was achieved. Looking back should not prevent from moving forward. Achievements can become your personal "bullies" blocking from going towards more significant achievements. This is why it's good to remember that you have achieved a lot, and yet have to achieve a lot more.

Some call it science, I call it art. Watch the video.

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?

The company I work for has a significant amount of web applications of a specific line of business. This line of applications started 8 years ago (I am with the company just for the last 3 only). Since I started to be interested in Domain Driven Design, felt strongly that this line of applications should be re-addressed with a DDD approach. But the resistance was enormous, motivating that "these are the pure data centric applications and there's no place for domain, the data is the domain and as a result of that it is a DATA driven design application".

I disagree.

Why do I disagree? Here's the theory I have that might be applicable not only to this case.

As a company that started web development 8 years ago under Microsoft wing, the natural choice for developers was classic ASP and SQL Server. With or without DDD, the business these applications were intended for had it's behaviour, rules, entities. Now with something like VB Script in classic ASP I cannot imagine proper tool for DDD, and on the other side, database was there to enforce the feeling of key components of design in shape and form of tables (Users, Selections, Benefits, etc.) So DB was a natural selection to grow the domain design, and incorporate some of the business logic (default values, calculations, etc).

Today, when we moved to C# and have a solid language to support good object oriented practices, database gets a role it should have had from the beginning -  persistence medium of the domain objects state. No logic, no design driving power, nothing of that.

How I can be sure about the theory? Over the years I see how painful the maintenance becomes, what challenges our developers face when they need refractor code, how non-trivial it occurs to do a trivial feature addition. The biggest from my point of view, is the fact that looking into the code, you cannot understand the business (behaviour, rules, logic).

This is why I believe those so called "data driven applications" should be reviewed closer, some of them are really "domain driven applications" not expressed well due to the luck of the proper tools at the time of creation.

Question. Doubt. Don't accept just because it's widely accepted.

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

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 than 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 have your good friends with ya.

Who am I calling out?

Terry Thibodeau

Karl Seguin

Glen Little

Going through the PDF document Karl Seguin was kind enough to share with all of us, could not not to agree with the written - quoting:

The real reason we’re spending a whole chapter on decoupling (which layering is a high-level implementation of) is because it’s a key ingredient in writing testable code. It wasn’t until I started unit testing that I realized how tangled and fragile my code was. I quickly became frustrated because method X relied on a functional class Y which needed a database up and running. In order to avoid the headaches I went through, we’ll first cover coupling and then look at unit testing in the next chapter.

Recommended reading.

More Posts Next page »