Thursday, December 11, 2014

Who is or who is not Architect


The following is a dialog between 2 individuals with the job title of Enterprise Application Architect. Let’s call  them A1 and A2:

 

A1: what are the CA warnings? What is the road map to eliminate them?

A2: let me send you an link from MSDN on these warnings. Microsoft did a good job on providing root cause, description, how to fix it and so on…

A1: do not give me work to do,  I am not going to read them all. I am an enterprise Architect, I only care about the enterprise architect at the high level.

A2: let me give you an example of CA warnings, CA1704 identifiers should be spelled correctly. The description is “The name of an externally visible identifier contains one or more words that are not recognized by the Microsoft spelling checker library”

A1: what is the methodology to fix this type of warnings?

A2: you correct the spelling of the identify to make them confirm to English dictionary.

A1: what, it has to be in correct English spelling? It is just a variable name, I can name it in any way I want!

A2: in modern programming, identifies ( class, property, method, local variables) need to be named following Pascal or camel name standard with proper English spelling of the wards. Failure in doing so would  result in this Code Analyses warnings.  If our programmers thought the way you think, we would have much more warnings than we do now.

A1: How to fix it then?

A2: let me show you an example on how to fix them, ( open up Visual Studio with the project opened)…

A1: I do not want to see Visual Studio, I just want to know methodology or road map on how to fix them

A2: that is what I plan to show you how I fix it as a programmer working on the code

A1: I am an Enterprise Architect,  do not show me these detail stuff

A2: (do not know what to say)

M1: A2, do you know what to do after this meeting? Do you know what A1 wants?

A2: I am confused, based on what I know on the subject, what I have provided is what he needs, it is just that he does not understand what I wrote. If you show what I have here to any software developer,  they would understand what I mean and able to follow what I wrote here to do what he or she needs to do. It I just A1 does not understand the business we are in…

M1: A2, since you did not provide what A1 asking for, and unable to provide the solution A1 is asking for. I will get someone who can…

A2:  I am not sure A1 knows what he is asking for or what he asks for even exist..

The conversation ends then, my friend (A2)  told me with frustration on his face…


This reminded me a book I read a year ago, the title is “Microsoft .NET: Architecting Applications for the Enterprise”. In the book the author wrote the following on who “architect” is…

 
every architect is a born developer. To take the metaphor one step further, we could say that the class Architect inherits from the class Developer and adds some new methods (skills) while overriding (specializing) a few others. Becoming an architect is the natural evolution in the career of some developers. The basic differences between an architect and a developer are experience and education. You gain experience by spending time on the job; you earn your education from studying good books and taking the right classes. In addition, an architect has the ability to focus her vision of the system from a higher level than an average developer… As we see things, an architect is, among other things, a better and more experienced developer. We don't believe there's value in having architects who just speak in UML and Visio and leave any implementation details to developers. At least, we've never found it easy to work with these people when we've crossed paths with them.


According to ISO/IEC, there are not various types of architects. An architect is an architect. Period.
 
It is fine to have multiple architects on the same project team. Likewise, it is fi ne, if not desirable, that different architects have slightly different skills. But they remain just architects, working on the same team on the design of the same system. And architects also have a significant exposure to code. They work out the design of the system but then work closely
with developers to ensure proper implementation. 
With that, I couldn’t help by asking, is A1 really an architect?  An enterprise architect in .Net project, does not know how to operate Visual Studio non wants to look at Visual Studio, What value this type of architect can offer to the project?

Sunday, November 30, 2014

Anti Pattern for December Fast Beats Right


The title of the anti-pattern is Fast Beats Right. The sub title is “A few hours? We don’t have that long”

The elaboration is read as: The practices of rushing a project and taking shortcuts to meet a delivery deadline, usually resulting in poor quality work that will require more effort to maintain in the future


This link provides some further reading on the anti-pattern ( including an interesting photo). For your convenience I quote it as following:

The Fast Beats Right ant-pattern alleges that it is always better to just get something done, regardless of quality, than to invest any effort into doing the job right.  In software development, this quickly leads to taking on Technical Debt, which can be useful and worthwhile in order to meet short-term deadlines.  However, unless it is paid down quickly, its long-term consequences can eventually lead to project failure.

Quotes


"There's never enough time to do it right, but always enough time to do it over." - Jack Bergman

In my decades of software development career, I realized that the some of those who practices this anti-pattern did so intentionally. They just want to get things done and do not want to invest time and effort to do it right. I have seen many in project leadership position do so intentionally.  The long lasting effect to the project is devastating. At the end of it, the project will pay back the technical debt  with interest, sometime it could means failure of the project. There are also people who did so  unintentionally, Due to lack of knowledge and or discipline in software development , programming,  they did what they know how to do, but not necessary the best way. If you ask them why they did what they did, likely you will get response “I do not have time for it, I was in the rush. In order to do what you are talking about, I need more time.” The reality is that even if you give him the time he is asking for, he would not know how to make use of the time and produce better result. “I need more time” is nothing more than an “convenient excuse”

This remind me watching adults playing chess when I was a kid. They took time to think and think,  in most of time, my patients s ran out before they made next move.  I thought I got the next move way before they do…. But when my daddy one day agreed to play the game with me, I lost the game terribly, When daddy asked me to time more time to think before making move, I realized I do not know how to use the extra time to think, what to think, how to think. I end up still making bad move. To use the time effectively one need to be skillful and knowledgeable. The same is true in software programming.  Less qualified developers meet with less qualified architects , project managers will likely result in “Fast Beats Right”  and “Fast Beats Right” will likely result in more difficult down the road, or even the failure of the project. At the end of it  have needing to "do it over"

Anti Pattern for November Smoke & Mirrors

Anti Pattern  for November Smoke & Mirrors



The title of the anti-pattern is Smoke & Mirrors AKA Marking Driven Dev elopement

 
The elaboration is read as: The Process of showing a demonstration to end-user without explaining that it is not production ready. The user’s exceptions are then based on the impossible promises made by the demo


This link provides some further reading on the anti-pattern ( including an interesting photo). For your convenience I quote it as following:

The practice of showing a customer "smoke and mirrors" and then hoping the engineers or developers can build it has been around for as long as sales and marketing people have had jobs.  As long as what's being sold can realistically be delivered, this practice works great and ensures there is continued demand for new and improved products and services.  However, when the customer is told to expect the world, and typically within an unrealistic timeframe, that's a recipe for disaster.  Strive to under promise and over deliver (a.k.a. Deliver more than expected) wherever possible, and work closely with customers to develop the product so they see it grow from idea to finished product and aren't surprised at any point to learn that the full-featured demo they thought they saw was really just a bunch of wireframes and animations with nothing behind them.

 
The quote of the month is :


"Under promise; over deliver" - Tom Peters

 
In my decades of software development career, I realized that the some of those who practices this anti-pattern did so unintentionally. Due to lack of understanding on the complicity software development, when the developers show them a “work in progress” version of the system, they are so eager to show it to the end user with that understanding that the job is done and the developers can move on to another project. To them, “database design is put together some tables and put some columns  into each table” “programming effort” simply means write a few pieces of code and do some stuff”

Even if the system is as prototype stage, they would have no problem  to claim “the system does exactly what the end-user wants”.  The worse thing is that when the end-user complain the quality of the system, they pass on the blames to the developers who wrote the code and who told them it is not ready. I hope you are not working with those “architects” or “Project managers”. As for me, I have had a fair share of such experience in my career,  the way I handle them is in 2 stage, when I still hopeful in getting them to see the reality, I try my best to educate them, lead their perceptions towards reality.  When I realize that it is impossible to pull them out of their perception and they are determined to continue to lie to themselves, I will try to “state the fact as it is in writing, let them interpret the fact as they wish.”

Sunday, October 5, 2014

Anti-pattern for October Franken Code

Anti-pattern for October Franken Code

The title of the Anti pattern is Franken Code, the sub-title is” It's alive! What could go wrong”

The elaboration is read as:  Code consisting of bits and pieces of other, possibly unrelated, code that only barely performs its function and is prone to error. Much like Frankenstein's monster, such code can wreak havoc on users


This link provide some further reading on the anti-pattern (including an interesting photo). For your convenience, I copied some here:

Frankencode refers to code that was never designed to work together, being pulled into a single application and held together with duct tape, baling wire, and maybe some Adapter design pattern usage. While software reuse and compatibility are desirable, frequently software that has been developed independently is written using incompatible assumptions and design decisions. Thus, when integrated together, the result can be clumsy and poorly architected, at least when compared to software that was designed to work together within the problem domain being considered.

 Quotes
"...learn from my miseries, and do not seek to increase your own." - Mary Shelley, Frankenstein
The following is a story a close friend of mine told me:
Not long ago, I came across a  Web application. The project was established as a fixed bid contract by iterative delivery scheduled on features. in each iteration. The developers are working hard just for that feature assigned to him or her. There was no refactoring effort, no design effort, and you guessed, no unit test case as well. Just coding and coding...
I have tired very hard to tell the engagement lead, project manager and the "Solution Architect", ( I put the quotes on the solution architect, as it is a Net project, but the solution architect is a Java guy who could barely able to move around within Visual Studio) that this would create problem down the road. with feature based iterative delivery, without refactoring, you would have a collection of disorganized code block; without automat unit test, refactoring would be very risky to the stability of the codebase.
 
3 months into the project, we got a codebase with lower performance, low maintainability and high cyclomatic Complexity. From vertical point of view, each feature looks like the only feature in the system. From horizontal point of view,  All methods and classes look disorganized to the extend beyond anyone's imagination.

In this project, they did not get the Franken Code from somewhere else, they produced Franken Code themselves.

Ok, This is the story I got about producing your own Franken Code.  in Software development business, loosely coupled and high cohesive are every architect's goals. If you are doing traditionally water fall process, do have a proper design after you collected all requirements; if you are doing agile or any feature based iterative delivery, Collective ownership, unit test and refractory are your best friends. if you are taking bites from other source like Nuget or download them from the internet, that is fine as we all do that. but you need to do it with your eyes open. the following are some important aspects to be aware of when you do that:

1. you want to get something in the framework level, for example, the library to interact with Web Api service, the library to interact with database. you would not want to get a third party package take care of your business logic.
2. you want to get it from reputable source.  Microsoft, Nuget.org, Codeplex, GitHub
3. you want to get the package that is meant for the net framework version and the visual Studio version. any compatibility issue would cost you trouble down the road
4. you want to review the code after you get them into your project

  
   
   

Thursday, September 4, 2014

Anti-pattern for September The Blob

The title of the Anti pattern is The Blob, the sub-title is” Doing everything all at one is a best practice”

The elaboration is read as:  A class in an object-oriented system that monopolizes the processing while other classes primarily just encapsulate data. this results in software that is more complex and harder to troubleshoot and maintain.


This link provide some further reading on the anti-pattern (including interesting photo). For your convenience, I copied some here:

The Blob is an anti-pattern that describes a class which resembles the monster from the 1958 film The Blob, which absorbs anything it touches and grows larger and larger over time. Such classes are similar to God Objects and over time lose any focus they might once have had. Blob classes violate well-known OOP principles such as the Single Responsibility Principle and the Open/Closed Principle, and tend to be more expensive to maintain and lead to Big Ball of Mud systems.Rather than allow a class to expand like The Blob, refactor using Extract Class and create smaller classes that each have a single responsibility.

 Quotes
"Multitasking is the art of distracting yourself from two things you you’d rather note be doing them simultaneously.”
- Anonymous
 Not long ago, I came across a  windows application. The application handles 3 different categories, more than 170 different transactions for a state government agency. There are distinguished business rules, processes for transactions in each category and specifically in each transaction.
For each transaction, there are 5-10 steps user need to go through to complete the transaction. Steps for different transaction category and different transaction are different and configured in a database table.
However, in the design I saw only one Window Form named as Transaction Detail Form, which is used to handle all different transactions in various steps.
Similarly in the business layer, I saw a huge class call Transaction Business Object, it has over 8 thousands line of code,  close to 500 members.  the highest member level of cyclomatics Complexity is over 170 (it was over 1000 when I took it over)
This is a clear case of “The Blob”, Transaction Detail Form and Transaction Business Object are two biggest Blobs among the rest.

Sure enough,  it is easy to break, hard to maintain and very difficult to troubleshoot.
In object oriented design,  the rules you want to follow are: 1) No repeating logic 2) no redundant functionality. In this case when a Business Object is instantiated to handle one specific step of one specific transaction, the object is much powerful than the task it is given.  when you change something in the class for one specific transaction, unintentionally, the code change affect other transactions.

Wen you are in the design phase, pay attention to the rule of “one thing and one thing only”, when class handles to many functionalities, you want to break it to smaller classes. When you design class model, you want to give each class a specified scope and role in the system.

When you are given a code base like the one I had, you want to be careful bot to break existing functionality while you take effort to fix the Blob issue.  What you want to do is to design a new set of object inheritance hierarchy and make the original Blob class be the base class and let the rest of code base use these sub-classes where the blob class was used originally.  I am sure you want to give each sub-class a clear defined scope and role.  At this point of time, all sub classes are empty. all we are doing is to create place holders for various sub classes. because there is no business logic changes, the change is less risky, even if we forgot to change some reference, it is fine, as the functionality is still in the original blob class. a good test to see if you have completed this step is making the originally blob class an abstract class. if you are able to do that without build error. you are good.

Once you are done with that, you can start to move business logic specific to certain transaction or specific to certain step to its rightful home in the newly defined object hierarchy.  as you slowly making progress in this migration process, you will see the blob class start to shrink, and these empty sub-classes start to have something meaningful.

However, this is the technical aspect of the issue,  to achieve what I described here you must not  underestimate the non technical aspect of the issue.  The leadership’s recognition of the issue and commitment to resolve the issue are critical.  Like basketball game, it is a team sport, and all listen to the coach. if coach does not believe the shooter is tired or not performing well, he stays on the game. If you, as a team member, making too much noise, you might get yourself out of the game. Similarly, if the leadership does not believe this is the problem, the problem will stay.  The worse thing is that the longer the problem stays the worse the problem will be and the bigger negative impact on productivity. this is what I call "too busy to do something to save time."
 

Thursday, August 28, 2014

Announcement of Windows Store App and Windows Phone App Development Blog

Hi, All,

I took the effort to reorganize my blogs. with that effort I created 2 new blogs, one for Microsoft Mobile App development ( windows Store App and Windows Phone App); One for Apple iOS app (iPad and iPhone) development. I have migrated most of relevant posts to these 2 new blogs and I will continue the migration process.

  http://peterlumsmobile.blogspot.com/

http://peterluios.blogspot.com/

http://peterludotnet.blogspot.com/

http://peterlusql.blogspot.com/

http://spellingchampionapp.blogspot.com/




these are the links to the newly created blogs and 2 other blogs, Enjoy and your comments are most welcome.


Thanks.

Wednesday, August 27, 2014

Inversion of Control (IOC) and Dependency Injection (DI)

For some time, I wanted to write something about this topic. it was largely due to my laziness, until now.  well. I guess I overcame my laziness today, and took the effort to get to this topic…


in most of program we write, there are always 2 parties involved, namely provider and consumer. when you write a method which instantiate another class and invoke a method of the instantiated class,  the code you are writing is the consumer, and the class you are instantiated is the provider. the same class in different context could switch its role between consumer and provider.  however, there is one common characteristic between the consumer and the provider, that is the consumer have the control and calls the provider.

Inversion of Control ( IOC) is a mechanism by which the control been transfer to the provider, in another word : let the provider take the control.  the over all goal of IOC is to break the dependency between the consumer and the supplier and yet let them communicate freely. if you take a closer look at the IOC implementations, you will find there are a few different implementation of it. I am going to list them below and give some of them some more detail elaboration on some of them:


Delegates

most of modern programming language supports Delegates, with the exception of Java.  if you look back at any declaration statement 

People myManager 

People is a class defined somewhere else, myManager is a variable can take any instant of People class. 

in 

DayEndOperation myDayEndOperation 

DayEndOperation is a Delegates defined else where, and myDayEndOperation can take in any instance of DayEndOperation

like in the class case, you can invoke the method or property of the class by myManager.Name or myManager.Approve ( yourRequest). in the case of delegate, you can invoke the delegate. you can pass around the delegate as parameter. This is very important as you create a delegate from consumer class and pass it to a method of the suppler class. and let supper class decided when and where to invoke it. 

Event 

Event is a special application of Delegate.  the suppler class defined certain events, when the consumer class instantiates the supplier class, the consumer class get to defined event handlers to react to these events. in the course of execution of the suppler code, the supplier class fire up certain events and in react to the firing of the event, the consumer’s event handling logic get executed.  the key is the supplier took over the control and calling the supplier code. underneath any event handling mechanism, you will see a delegate as part of implementation.


Dependency Injection

Dependency Injection is a mechanism to break the dependency from the consumer to the supplier by introducing Interface.  in this case, 2 more players got into the picture other than consumer and supplier,   ISuppiler and  container. in compiling time, consumer only depends on ISuppiler instead of the solid implementation of ISuppiler. in runtime, container injects the solid implementation into the interface. the injection could be done in code, or by configuration. when it is done in configuration, that means, in run time I can switch the solid implementation of the interface without recompiling the consumer code. This characteristic make it very good for doing coded unit test, because I can inject some stub implementation into my test method to test my consumer code without calling the real supplier components. there are constructor Injection, Property Injection and Method Injection. most of DI container support all of them.  I personally worked on Unity and NDepend.

Service Locator

Suppose your consumer classes have dependencies on an external service , whose concert types are specified sty compile time. The following limitations are posed to the system:
 1. to replace or update  the external service, you need to update your project reference and recompile the solution
2. the external service must be available at compile time
3. your class is difficult to test in isolation because it need the external service to run


Service Locator pattern introduce another element, call <Service Locator>  and let Service Locator handle the dependency of the external service.  in detail implementation, you could inject different locator to your consumer project, or you inject external service into your Service Locator  or you use Factory Pattern to handle the instantiation of the external service.  if the service provider provides respective interface of the service, DI is preferable, otherwise use factory pattern. this preference is due to the fact, only doing DI you will remove the dependency of concert type of the service and only when the interface is provided, you can do DI.

Wednesday, August 13, 2014

Anti-pattern for August: Walking in a Minefield


The title of the anti-pattern is: Walking in a minefield. The sub title is “the application’s ready for production… you go first."

The elaboration is read as:  When a product (known to be incomplete) is released prematurely, this forces users to stumble through the system finding bugs while the development team scrambles to resolve them.




This link provide some further reading on the anti-pattern (including interesting photo). For your convenience, I copied some here:

When software is released before it is ready, and users of the software are made to find all of its bugs and shortcomings, they're made to feel as though they're walking in a minefield. It's important to release software as quickly as possible, in order to minimize feedback loops, but what is released should work so that users do not lose confidence. Each new release should be more stable than the last, and should incrementally add new functionality. If the system is constantly shifting such that things that work one day fail the next, eventually users will demand a different system altogether, and the project will fail.

 Quotes

"Software undergoes beta testing shortly before it's released. Beta is Latin for 'still doesn't work.'" - Anonymous

There is a related anti-pattern, it says “let’s test it in production.”
 

The commonality of them is releasing a untested product to the end user, with the hope that the product is not buggy or if it is buggy, the users will help to identify the bugs for the development team to fix so that the software product can be useable.


From principle point of view, this is not a good practices, when the product is released for production, it need to have some kind of quality standard. Release an untested product to production is not fair for the users or client. It may very well negatively impact client’s business operation and could damage their reputation or expose client to other tangibles damage.

From technical point of view, some bugs could cause loss of data, and the lost data may not recoverable even if the bugs are fixed afterwards.

The biggest risk is that when an untested product exposed to its user, the users might very well discouraged by the buggy product and hence reject the product totally. 


However, in my decade’s application development experience, I have seen many incidences of the anti-pattern. I remember a few years ago, I attended a high level project strategy meeting. The meeting is to establish a strategy to address the issues of lacking of resource and time for developing and conducting test cases during the stabilization phase of the project. To my surprise, the decision was cutting down the number of test cases  significantly. The justification was: there is no enough time.  When I heard that, I could not believe my ear, this is exactly, “let’s test in production”

My take on it is simple, “Never”, never do that! An experienced project manager should be able to project such project risk and mitigate such risk so that it will never become an issue to be addresses in the project.  From technical resource point of view, when you are brought into a project to handle the crisis, you should take positive attitude do your best to recover from the crisis. I personally have been in such situation many times. The advice I could offer are the following:

 
1.    Backup database often, make sure the raw data entered by user is stored in database correctly. In production system, nothing is more important than data.

2.    When patching data error generated buggy logic, make sure the patching logic does not get extended beyond its intended scope.

3.    Fixing bug and patching data need to be in sync.

4.    Apply pair programming to reduce human error.

5.    When fixing bug, do your best to respect the original design and minimize the changes to be made. It is always risky to change design when product is in production.
 
Finally, remember there is no bug is small in production.  You could never be more careful. As the title said, it is a minefield, you do not want to walk in the minefield. When you are forced to walk in the minefield, be absolute careful.   

Friday, July 4, 2014

Anti-pattern for July Flags over Objects

It is 4th July today.  after watching fireworks at Columbus downtown last night and pressure washing my patio and side walk in the morning, I got to sit in front of my PC.

Yes, it is July now, it is the time for Anti-pattern for July.

This is how it goes.

The title of the anti-pattern is : Flags Over Objects

The subtitle is : So easy you can add another twenty options

The elaboration for the anti-pattern is:  instead of using objects, Polymorphism, or delegation, a flag is added to the class and exposed for public consumption. this often leads to many flags being added in lieu of more maintainable code.

The quote is “ The best thing about a Boolean is that even you are wrong, you are only a bit off”

 The link to the anti-pattern is http://deviq.com/flags-over-objects


The Flags Over Objects anti-pattern occurs when behavior is written outside of an object by inspecting flags (such as status codes), rather than within the object itself. This violates the Tell, Don't Ask principle, and results in chatty interfaces and distribution of behavior that probably belongs within the object. Working around this issue, one will often experience the Shotgun Surgery coding smell, in which many small changes to many files are required in order to make changes to the system. There are many ways to address this anti-pattern. In the worst cases, the State design pattern can effectively be used to bring all state-transition related behavior into the object, or at least into objects specifically constructed to handle the responsibility of state and state transitions.

Take an example, if you see one class  (Transaction Business Entity) representing many business transactions and a flag (Transaction Type) as a public accessible property indicting which business transaction it is, you are in front of “flag over objects” anti-pattern.
it seams intuitive and easy to have this type design  when you add first flag to the class. but before you realized you will be attempted to added more and more.  on the other end, you will have many places making logic decisions based on the value of the flags.  that is where the bad smell comes out. First of all,  these  conditional logic are all over the places ( outside the class), secondly, it is more than likely they got repeated in different places. it is commonly recognized that code in that nature is difficult to debug, difficult to change.  Due to  large number of conditional logic, the cyclomatic complexity of the codebase will go no way but high.
On the other hand, one of the characteristics of OOP is lack of conditional logic.  When new business transaction types are added to the codebase, instead of introducing flags or switches,  sub-class, interface or delegation are used, in the beginning it could be seen as lots of more work as comparing to using flags. but the effort spent on proper OOP design will pay back in the long run. I promise you, your successors will sure thank you for handling them  more maintainable codebase…
So the proper pattern is : Object over flag.  whenever you see a flag or a enum type of property, you ask yourself,  is this indicating the same thing with different characteristic or different thing all together.  if the answer is the second one, you are highly encouraged to consider other OOP technics like objects, Polymorphism, or delegation in lieu of the flags.

Monday, June 23, 2014

FW: Compact DB, Smart Client and Application Caching

Around June 2004, Microsoft released Smart Client Architecture and Design Guide, in the article, Microsoft listed 3 important characterizes of Smart client application:
 
  1. It offers rich user experience like normal window application, unlike normal web application
  2. It works in disconnected mode. ( MS call it Occasionally Connected)
  3. It can be deployed by “no-touch deployment” technology and capable of self-update
 
An example would be like a salesman carries his laptop walking into his customer office, he should be able to show the product catalog, take orders  when talking to his customer  when the laptop is disconnected.  However the orders will be uploaded to the ERP or MRP system, and you should be able to synchronize the product catalog  when he get back to his office and connect the laptop to the company network.
 
To make it possible for the application to function in disconnect mode, the application needs to stored it transactional data and reference data…  To facilitate this kind of functionality, Microsoft introduced concept of Compact DB and database synchronization framework.
 
On the other end, around April 2003, Microsoft release Caching  Application Block as a member of Enterprise Library ( in fact, Avanade is the company behind all enterprise Library development, and I happen worked for Avanade for 3 years from 2004 to 2007). http://msdn.microsoft.com/en-us/library/ee957904.aspx
 
This is what it says about caching, “Caching techniques are commonly used to improve application performance by storing relevant data as close as possible to the data consumer, thus avoiding repetitive data creation, processing, and transportation.”
 
Okay, enough stuff about Microsoft technologies. Let’s move on to our life, BAM. First of all, I have reviewed all non-functional requirements of MI VBAM, it was not our goal to design and develop a smart client. It was not our goal to make it still functional in disconnected mode.    But we are using Compact DB and database synchronization framework.
 
If you look at the data that is been synchronized, you will find more than 70% of data is not supposed to be changed, the other 30% is just some reference data, there is no 2 way synchronization needed. no transactional data is involved in the synchronization process. Basically, we use it as caching solution.
 
To give you some feel about what kind of data we are loading to the compact DB and involved in the synchronization process, I list some tables ( not complete list, in total there 333 tables ) as following:
 
  1. REF_CUSTOMER_TYPE
  2. REF_ID_TYPE
  3. REF_CONTACTS
  4. REF_ADDRESS_TYPE
  5. REF_STATE
  6. REF_CITY
  7. REF_SUFFIX_CODES
  8. REF_COUNTRY_CODE
  9. REF_INTL_MILATARY_STATE
  10. REF_INTL_MILITARY_CITY
  11. REF_CONTACT_TYPE
  12. REF_MODE_TYPE
  13. REF_INDIVIDUAL_CHARACTERISTICS
  14. REF_BUSINESS_ROLES
  15. REF_CITY_ZIPS
  16. REF_COST_EXEMPT
  17. REF_DAMAGE_REASON_CODES
  18. REF_FUEL_TYPE
  19. REF_GROUP_TYPE
  20. REF_IMAGE_TYPE
  21. REF_NAME_TYPE
  22. REF_PREFIX_CODE
  23. REF_SALE_TAX_OUT_OF_STATE
  24. REF_SALE_TYPE_CODE
  25. REF_STOP_ACTION
  26. REF_TAX_EXEMPT
  27. REF_VEHICLE_BODY
With that, I am propose the following suggestions
 
  1. Review this 333 table to remove these tables that data is not manageable by user. A clear cut would be if we defined a enum in our code, for the same data, we do not even need the data in the server database… please refer to the link https://external1.collaboration.hp.com/external/MIBAM-R1/MI%20BAM%20Cookbook/Enum%20types%20and%20Ref%20tables.aspx for some detail.
  2. do away with Compact DB and synchronization framework.
  3. Employ Caching  Application Block to cache the data need to be cached in both Client (Process Controller) and server side (BO layer)
 
 
Just so you know,  Caching  Application Block is the application block that is most easy to be employed… 10 minutes would be enough for you to know how to use it… by doing this, the problem we are facing in Compact DB and database synchronization framework will no longer exist…
 

Duplicated Code and how to eliminate them

Number one in the stink program is duplicated code. If you see the same code block in more than one place, you can be sure that your program will be better if you find a way to unify them.
 
. When you see the same block of code in two methods of the same class, extract the code block into a private method and invoke the method from both places.
 
.when you see the same block of the code in 2 sibling sub-classes, extract the code block into a protected method in the base class and invoke the method in both places.
 
.When you see the code block are doing the same thing but in different way, extract the better code block into a private method and invoke the method in both places.
 
.When you see the duplicated code blocks are doing the same but on different target, extract the code block into a private method with some parameters, and then invoke the method in both places with different parameter values.
 
.When you see a duplicated code block in 2 unrelated classes, you have a few options. You need to decide which one make more sense from business point of view.
a.       Abstract the duplicated code blocks into an abstract base class and let the 2 classes inherit from it. (Be its sub-class). In another word, make them related by be the sub classes of the same base class.
b.      Encapsulate the code block in third class as internal/public read only property or method and invoke it in both place. This will also reduce class coupling.
c.       Abstract the code block into a public method in one class and let other class invoke the method in the hosting class. 
 

RE: bad smell code # 2 Long Method

I took a look at a codebase reviewed before and I found that the top 3 longest methods are as following:
Interface. InsertNADAData(String) As Boolean ( 774 LOC)
 
RegistrationNewUserControl. ValidateControls(Integer) As Boolean ( LOC 629)
 
RenewalRegistrationController. VehicleDetails(String, String, String, String, FormCollection, String, String, String, String, String, String, String, String, String, String, String, String, String, String) As ActionResult ( LOC 617)
 
If you happen to step into any of these members, you would agree with me when I say these code blocks are smell bad. They are very difficult to understand let alone maintaining them or extend them….
 
Let’s say how the experts say about long methods:
 
The object program that lives best and longest is these with short methods. Programmers new to objects often feel that no computation ever takes places that object programs are endless sequence of delegations. When you have lived with such a program for a few years, however, you learn just how valuable are those little methods are.  All of these payoffs of indirection – explanation, sharing and choosing. All supported by little methods. …. Since the early days of programming, people have realized that the longer the procedure, the more difficult to understand.
 
Okay, we accepted the call that “short method is good, long method is bad” but given the code base we have, how we gradually shorten the methods of thousands class in our code base?
 
.99% of the time, all you have to do to shorten a method is Extract. Find a part of the method that seems to go nicely together and make it a new method.
 
.If you find that you have a method with lots of parameters, you can introduce parameter objects to group these parameters into groups. (I am sure you would like to try this method on the third example above)
 
.If you find that you have a method with lots of temporary variables, you can move the related code block from your method to the class that is close to it as a read only property or method. (I am sure you have seen many of such examples from my code review comments)
 
After you have done all above, if you still end up with a long method with lots of parameters and local variables, it is time to turn the method into a class by itself. After you do that, all you original local variable become fields of the new class, then you can decompose the method into other small methods on the same object.
 
How do you identify the clump of code to extract? A good technic is to look for comments. They often signal this kind of semantic distance. A block of code with a comment that tells you what it is doing can be replaced by a method whose name is based on the comments. Even a single line is worth extracting if it needs explanation.
 
Conditionals and loops also give signs for extractions. If you have a complicated conditional (if-then-else) statement, extract methods from the <condition part>, <then part> <else part>. With loops, extract the loop and the code within the loop in its own method.

FW: bad smell code # 5 Divergent Changes

We structure our software to make changes easier; after all software is meant to be soft. When we make a change we want be able to jump to a single clear point in the system and make the change. When you cannot do this you smell one of 2 closely related pungencies, Divergent Changes and short gun Surgery
 
Divergent changes occurs when one class is commonly changed in different ways for different reasons. If you look at the class and say “well, I will have to change these 3 methods every time I get a new database, I have to change these 4 methods when month end process changes” you likely have a situation in which 2 classes is better than one. That way each class is changed only as a result of one kind of changes.
 
Now, go back to our code base, imagining that state of Michigan changed some policy related to driving license, the minimum age to be able to apply for driving license is not 16 and half years old, instead, it is 16.  How many places in our code we need to change?  ( short gun Surgery)
 
Take a look at TransactionBO class (it is 9320 LOCs in size), ask ourselves are the following statements true: this class contains business logic all DriverLicense, Vehicle, Placard, title and so on…   We have about 15 different TransactionBEs (TitleRegBE, DrivingLicenseBE , DocumentAuthenticationBE) and over 100 different transaction types. TransactionBO class has related logic on all of them. You will probably a group of methods for each transaction BE in this class. Sometime, you will find within a method, there is some code like “Select Case transaction.TypeCode”  or If TypeOf Transaction Is TitleRegBE”
 
When you look at TransactionBO, would you say something like “I need to change these methods if the process for renew Driver License changes, I need to change those methods if the process for register a newly purchased vehicle changed , the same goes for title, placard….”
 
Ok, we know there are this type smell in our code base, how to get rid of it. There are 2 different ways. One is consider surgical way one is consider non-surgical way.   Let me describe them in detail here:
 
Surgical way:
You scan through the class, and identify the members that is related to some specific type of operations (e.g. DrivingLicense operations), extract them in to a new class and change the rest of the codebase to use the new class instead of original class.  In this way the effect is immediate, the impact is large. So the effort and risk associated to it is large.
 
No Surgical way:
You add a new class (DrivingLicenseBO) for a specific type of the operation (e.g. DrivingLicense operations), and you let the original class (TransactionBO) be its base class. In the beginning DrivingLicenseBO is empty.  Then you make an announcement say “from now on, when you are doing DrivingLicense related operation you use DrivingLicenseBO instead of TransactionBO” as it is now, the effect is the same, as DrivingLicenseBO is a empty sub class of TransactionBO.  So other programmer including yourself, start to change their code to use DrivingLicenseBO instead of TransactionBO for DrivingLicense related operations. When this process is (almost) completed, you then can start to move methods specific DrivingLicense related operations to from TransactionBO to DrivingLicenseBO. In this way, the initial effort and risk associated to the change is much smaller, but it will take long time to complete the migration process.  
 
The end result of these 2 approaches is the same. The only difference is the process. Projects choose different approach based on their situations. If it is affordable for project to endure this kind of surgery operation, and you are confident with what you are doing, you should take up the opportunity to conduct the surgical operation. If not. You can at least start the process using the non- surgical process.
 
One important point to note that, when a class has “Divergent Changes” smell, it most likely will also has “large class”… when we eliminate “Divergent Changes” smell; we also work towards eliminating   “large class” smell.

FW: bad smell code # 4 Long Parameter List

I took a look at our current code base; I found the top 4 longest parameter list members as following:
 
TROrignalTransferTitleMessageBE.New(
ByVal TRStreet As String, ByVal TRCity As String, ByVal TRState As String,
ByVal TRZipCode As String, ByVal TRZipCodeExt As String,
ByVal TRNamePartOne As String, ByVal TRNamePartTwo As String, ByVal TR_Handicap_Sticker As String, _
ByVal TR_DLN As String, ByVal TR_Passport_Indicator As String, ByVal TR_Number_Of_Plates As String, _
ByVal TR_Dealer_Number As String, ByVal TR_Orig_Registration_Total As Decimal, ByVal TR_Registration_Transaction_Code As String,
ByVal TR_Title_Transaction_Code As String, ByVal TR_Tab_Number As String, ByVal TR_Plate_Number As String,
ByVal TR_Prev_Plate_Number As String, ByVal TR_Number_Months As Short, ByVal TRExpirationDate As String,
ByVal TR_Replacement_Tab_Indicator As String, ByVal TRCountyCode As String, ByVal TR_Model_Year As Short,
ByVal TR_Make As String, ByVal TR_VIN As String, ByVal TR_Body_Style_Code As String,
ByVal TR_Weight As Long, ByVal TR_Fee_Field_Change_Indicator As String, ByVal TR_Weight_Ind As String,
ByVal TR_Instant_Title_Code As String, ByVal TR_MH_App_Type As String, ByVal TRDPC As String,
ByVal TR_Graphic_Plate_Indicator As String, ByVal TR_Manufacturer_Plate_Format As String, ByVal TR_Insurance_Indicator As String,
ByVal TR_Payment_Code As String, ByVal TRFlashStatusPlateNumber As String, ByVal TRRemovedRegistrationFlashStatusCode As String,
ByVal TRAddRegistrationFlashStatusCode As String, ByVal TR_Plate_Description As String, ByVal TROrgCode As String, ByVal FirstLienName As String, ByVal SecondLienName As String, ByVal firstLoanDate As String,
ByVal secondLoanDate As String, ByVal titleFees As Decimal, ByVal fullRightsIndicator As String, _
ByVal specialCodes As String, ByVal specialUseCode As String, ByVal taxExemptReason As String,
ByVal foreignTitleSateCode As String, ByVal titleNumber As String, ByVal vehicleColor As String,
ByVal salesPrice As Decimal, ByVal mileage As String, ByVal firstLienStreet As String,
ByVal firstLienCity As String, ByVal firstLienSate As String, ByVal firstLienZipCode As String, _
ByVal firstLienZipExtenstion As String, ByVal SecondLienStreet As String, ByVal SecondLienCity As String, _
ByVal mailingCity As String, ByVal mailingstate As String, ByVal SecondLienZipCode As String, _
ByVal SecondLienZipExtenstion As String, ByVal mailingStreet As String, ByVal mailingZipCode As String,
ByVal mailingZipExtenstion As String, ByVal firstLienDPBC As String, ByVal SecondLienDPBC As String,
ByVal mailingDPBC As String, ByVal secondLienSate As String, ByVal specialMailerCode As String,
ByVal salvageParts As String, ByVal mileageBrand As String, ByVal mobileDealerNumber As String, _
ByVal taxExemptIndicator As String) ( 76 parameters)
 
DeleteTitleRegistrationBE.New(
ByVal PlateType As Integer, ByVal IsTempPlate As Boolean, ByVal PlateBackground As Integer, ByVal PlateSubType As Integer, _
ByVal VehicleUsage As Integer, ByVal IsPersonalized As Boolean, ByVal IsHandicap As Boolean, ByVal IsVanity As Boolean, _
ByVal ResidentAddressStreet As String, ByVal ResidentAddressCity As String, ByVal ResidentAddressState As String, ByVal ResidentAddressZipCode As String, _
ByVal ResidentAddressZipCodeExt As String, ByVal CustomerNamePartOne As String, ByVal CustomerNamePartTwo As String, ByVal DriverLicensceNumber As String, _
ByVal PassportIndicator As String, ByVal PlateQuantity As String, ByVal DealerNumber As String, _
ByVal RegistrationFee As Decimal, ByVal TabNumber As String, ByVal PlateNumber As String, _
ByVal PreviousPlateNumber As String, ByVal RegistrationDuration As Short, ByVal RegistrationExpirationDate As String, _
ByVal ReplacementTabIndicator As String, ByVal ResidentAddressCountyCode As String, ByVal ModelYear As Short, _
ByVal Make As String, ByVal ManufacturerID As String, ByVal VehicleBodyStyleCode As String, ByVal Weight As Long, _
ByVal InstantTitleCode As String, _
ByVal ResidentAddressDPCCode As String, ByVal VehicleType As Integer, ByVal CustomerType As String, ByVal OwnershipType As Integer, ByVal RegistrationType As Integer) ( 38 parameters)
 
 
AuditReportBPC. GetAuditDataDetail(ByVal auditID As String, ByVal RequestorName As String, _
                          ByVal Branch As String, ByVal WorkStationName As String, _
                          ByVal ChannelType As Integer, ByVal RequestorType As Integer, _
                          ByVal formName As String, ByVal controlName As String, _
                          ByVal cartID As Integer, ByVal completedTXNID As Long, _
                          ByVal inProgressTXNID As Integer, ByVal customer_Number As String, _
                          ByVal vin As String, ByVal startDate As DateTime, ByVal endDate As DateTime, _
                          ByVal firstName As String, ByVal middleName As String, ByVal lastName As String, _
                          ByVal plateNo As String, ByVal dateOfBirth As DateTime, ByVal ssn As String, _
                          ByVal sortOrder As String, ByVal isAllBranchesSelected As Boolean, _
                          ByVal binarySum As Integer, ByVal IISSessionID As String, _
                          ByVal ReqIPAddress As String, ByVal ReqBrowser As String, _
                          ByVal ReqBrowserVersion As String, _
                          Optional ByVal XMLMethodName As String = "Audit") _
                          As DataSet Implements IAuditReportBPC.GetAuditDataDetail (29 parameters))
 
 
DuplicateTitleRegistrationController.BulkVehicleDetails
                                          (ByVal aNext As String, ByVal aPrevious As String, ByVal aCancel As String, ByVal aReset As String,
                                           ByVal aSearchVehicle As String, ByVal aSelectedVehicle As String, _
                                           ByVal aRemoveVehicle As String, ByVal aGridName As String, ByVal aAction As String, ByVal aPage As String, _
                                           ByVal VehiclesGrid As String, ByVal ORVVehiclesGrid As String, ByVal WaterCraftVehiclesGrid As String, _
                                           ByVal MobileHomesGrid As String, ByVal SearchedVehiclesGrid As String, _
                                           ByVal SelectAllVehiclesGrid As String, _
                                           ByVal RemoveAllVehiclesGrid As String, _
                                           ByVal SelectAllORVVehiclesGrid As String, _
                                           ByVal RemoveAllORVVehiclesGrid As String, _
                                           ByVal SelectAllWaterCraftVehiclesGrid As String, _
                                           ByVal RemoveAllWaterCraftVehiclesGrid As String, _
                                           ByVal SelectAllMobileHomesGrid As String, _
                                           ByVal RemoveAllMobileHomesGrid As String, _
                                           ByVal SelectAllSelectedVehiclesGrid As String, _
                                           ByVal RemoveAllSelectedVehiclesGrid As String, _
                                           ByVal SelectedVehiclesGrid As String, _
                                           ByVal aFormCollection As FormCollection) As ActionResult (27 parameters)
 
 
I have looked around on what is the right number of parameters for a good API design. Numbers like 3, 5 and 7 popped up, but is pretty much common consensus that >= 10 are considered as too many, whither it is in Java or .Net program…
 
 
This shows how far away we are from having a high quality code base… maybe we can spend some time on these long parameter list methods, at least we should stop making them longer than 10.
 
 
There are 2 common approaches in shortening the parameter list.
<![if !supportLists]>1.       <![endif]>Replace the parameter with a method call. What it says is that instead of letting the caller provide the value for the parameter, the member makes a call to get the value inside the implementation of the member.
<![if !supportLists]>2.       <![endif]>Intrude Parameter object. What it says is that instead of passing these values through big list of individual parameters, we pass these values through a parameter object; the parameter object is an instant of a class or a structure, which has many members in it.  However, when we blind parameters into a class or a structure, we need to make sure we only blind these related parameters together.  Take an example here:
 
GenerateAuditReport (parameter as AuditReportParameter)  where AuditReportParameter is a structure defined as following:
 
Public Structure AuditParameter
    Public AuditID As String
    Public RequestorName As String
    Public Branch As String
    Public WorkStationName As String
    Public ChannelType As Integer
    Public RequestorType As Integer
    Public FormName As String
    Public ControlName As String
    Public CartID As Integer
    Public CompletedTXNID As Long
    Public InProgressTXNID As Integer
    Public CustomerNumber As String
    Public VIN As String
    Public StartDate As DateTime
    Public EndDate As DateTime
    Public FirstName As String
    Public MiddleName As String
    Public LastName As String
    Public PlateNo As String
    Public DateOfBirth As DateTime
    Public SSN As String
    Public SortOrder As String
    Public IsAllBranchesSelected As Boolean
    Public BinarySum As Integer
    Public IIISSessionID As String
    Public ReqIPAddress As String
    Public ReqBrowser As String
    Public ReqBrowserVersion As String
    Public XmlMethodName As String
End Structure
 
<![if !supportLists]>3.       <![endif]>If you look at these long parameter list examples above, 2 of them are used as constructor. Starting from Visual Studio 2008, MS offered an easy way to instantiate object, it call object initializer. Take an example here. With this syntax, these long parameter list constructors are no longer needed. You might notice in the syntax bellow, you provide value for property by property by name, instead of depending on parameter order when you use constructor. When your parameter list is long, and you provide values for them based on order, you could easily make some mistakes that are hard to debug, especially they are all with the same type. So it is highly recommended to use this object initializer syntax.
 
Person = New Person() With {.FirstName = "John", .LastName= “Doe”, SSN = “123456789”}