Do I put this method into a New Class? Decisions Decisions…

Technorati Tags: ,,

These days I’m working a lot more on not just code features, but also more architecture from scratch.  That is, creating many new Abstract classes, Non-Abstract classes, Interfaces and utilizing more and more Design Patterns.  Thus every field, member, property, etc. created in the class or interface heirarchy tree becomes very important in how you define them and where you define them as well as any dependencies that they may be carrying.  You try to create a class or interface structure with as least # dependencies as possible, so that a change to one object will not affect the other (thus a good separation of concerns in your design).  You’re not just creating a class here and there, but you’re creating the architecture (class trees, foundations for which developers on the team will utilize later). 

With that said, decisions often come down to the simplest & smallest forms when you look at architecting classes or interfaces. It’s not all about the big decisions every time.

The goal is to create good software right?  At least that is what your team & management should have in mind other than just meeting deadlines to please the customer & spitting out code at lightening speed which seems to be the expectations today from the business which often turns into horrible architecture (code & run) as a result.  I’m an advocate of true Agile methodology but not really into Extreme programming personally.

So what defines good software?  An excellent measurement to continually check your code by running it through the ISO/IEC 9126 Standard list which states a very nice list that measures the following in terms of design and determining if your software is meeting business requirements. 

I’m going to reference a table from the book Microsoft® .NET: Architecting Applications for the Enterprise (PRO-Developer) based on the  ISO/IEC 9126 Standard:

(I also appended some of my own thoughts in parenthesis below, and highlighted what I thought was most important from a technical standpoint)

Functionality

- Indicates what the software does to meet expectations

- It is based on requirements such as suitability, accuracy, security, interoperability, and compliance with standards and regulations defined by the customer

Reliability

- Indicates the capability of the software to maintain a given level of performance when used under special conditions

- It is based on requirements such as maturity, fault tolerance, and recoverability

- Maturity is when the software doesn’t experience interruptions in the case of internal software failures

- Fault tolerance indicates the ability to control the failure and maintain a given level of behavior

- Recoverability indicates the ability to recover after failure

Usability

- Indicates the software’s ability to be understood by, used by, and attractive to users. 

- It dictates that the software be compliant with standards and regulations for usability

Efficiency

- Indicates the ability to provide a given level of performance both in terms of appropriate and timely response and resource utilization

Maintainability

- Indicates the software’s ability to support modifications such as corrections, improvements, or adaptations.

- It is based on requirements such as testability (unit testable), stability, ability to be analyzed, and ability to be changed (example: can you easily change out the current DL and create for example your own custom DL?)

Portability

- Indicates the software’s ability to be ported from one platform to another and its capability to coexist with other software in the environment and sharing common resources

Now anyone could easily just skim over the bolded list and really never understand them unless they take time and really care to engage in this list and apply to the development shop. It’s easy to just gloss over the bullets above and say “yea, yea, I know what they mean”.   But do you really?  I bet you that you don’t unless you really take the time to understand what each is and in context to creating maintainable and extensible code.  And I bet if you think you do know, that it’s most likely not even being applied in terms of a team standard or some form of checks & balances on your team often.  If it is, I applaud you and the team.  This would be a very good list for code reviews as well as part of a team standards doc.  While it’s general, it also specifies specifics as you can see above so that there is no confusion what they mean at a high level.

In my opinion, every development lead or manager should ALWAYS use this list as part of your overall tools to make sure that your shop is producing is GOOD software and underlying code and patterns support these points above.  And I think one of the best ways to start doing this is to analyze your code base to see if it’s easily Unit Testable as it stands today.  If not, then you have some work to do to refactor or make sure new classes or interfaces are going foward.   Checking if it’s unit testable is a very good measure to see if your code is maintainable and extensible at the same time.  Using the SharePoint API with DataSets is not easily unit testable.  It’s tightly coupled which goes completely against unit testable frameworks.  That’s just one example of bad software.

Now for a simple example at work the other day where a small routine decision in architecture really becomes an all too common very important decision for extensibility, testability, and maintainability hit me again.  I am currently working on creating a small framework that will allow us to utilize a third party REST API in order to offer some new features & functionality to our customers for a very good reason via our public e-commerce website.  This project probably will consist of around 20-40 classes or so, and maybe a couple interfaces if it makes sense for some code that we may be able to reuse between some projects.  Fairly small but definitely challenging and complex to say the least based on some of the things we’ll have to incorporate on our side and also get working on the SOA endpoint side of things.

Anyway, it came down to when I created an APIRequest.cs class in my project.  This class would represent an HTTP API method call request to the SOA API server in order to call a method over to the SOA REST API.  This class will not only hold the data (fields) in the request but help to form the request string itself.   I had to make a decision whether or not to put a method of mine SendAPIRequest() in my APIRequest.cs class or move it to a separate class that would do the sending processing related work for sending the request itself. 

In the end, I thought about the Single Responsibility Principal (part of the SOLID Principal) that a friend had reminded me of.  That principal states that a class should only have a single responsibility.  And the responsibility that I defined for my APIRequest class was only to hold the state of a request (the data) and to form the string for the request.  If you find your class starting to do other things (via methods) that doesn’t really make sense to the original class’s purpose (and hence it’s name should also communicate its purpose), then it’s time to break that method(s) or those fields out into a new class.  Breaking it out into a new class made sense was to represent the request data, not to do the work sending the actual request.  So that called for a separation of logic into a new class to handle the actual work to send the request.  This ensured that I was satisfying the SRP principal as well as are easily testable in the future.

That is just one example of a simple decision that I had to make but in the overall scheme of things is a very important decision to:

1) Ensure quality software is produced not only for the business

2) Ensure that the “team” can change the code easily and maintain those classes later without affecting each other (breaking change) down the road

I would not put this method in a utility class because I know that for sending the request, I’m going to need several methods that separate out the logic to do so possibly.  And I also want the fexibility to test the logic as well as extend that functionality later for sending a request.  I want that extensibility to be there in the future so by putting that method in a regular class, not a utility class.  I’m very careful about Utility classes.  You do not want to use a Utility class as a bucket to put all of your business logic in.  They should be held in logical classes unless those utilities are general enough to be reused elsewhere or does not make sense anywhere else.  Do not put all your business logic methods in Utilities is what I’m saying.  You’ll end up with one Utility class with 1000+ lines in it which makes it a big pile, hard to read, and non-testable.  That’s why we use classes, inheritance, and thus separate concerns in terms of logic.  Utility classes have their place but be careful what and how much you put in them.

Conclusion:  Such a small decisions have huge impacts later down the road and one of them is determining where certain class methods should lie in your overall class structure.


Print | posted on Sunday, January 04, 2009 10:28 PM

Comments on this post

# re: Do I put this method into a New Class? Decisions Decisions…

Requesting Gravatar...
I agree to most of the contents of this topic, but IMHO this analyzing and "do-it-bookright-or-dont-do-it" mentality in many cases ruins the development of a system. Yes it should be testable, yes it should be flexible, but when I see people laying down days or weeks "designing" the optimal, abstract, DL so that it sweetly can be replaced by changing a few configuration settings - my head aces and I want to shout NOOOOOO!!!! In a medium to large sized system (where these kind of designs take place) - how often do you think the datasource will be replaced? How often do you think the datasource will be changed during a system lifetime? Once, twice, once a week....? Of all systems I've been involved in, NONE has replaced their datasource! A system established on Oracle has continued with Oracle, a system on SQL Server also continues on SQL Server... Ofcourse, you should make it easy maintainable, but that is way different than making it easy replacable! All in all I think the pattern/design/practices discussions of today are bloated and brings very little to the table. Stay with common sense and it will boost both quality and speed!
Left by jason on Jan 08, 2009 1:10 AM

# re: Do I put this method into a New Class? Decisions Decisions…

Requesting Gravatar...
I completely disagree with the post from Jason. Where to begin with the problems of such ignorant thinking! First to address the statement “but when I see people laying down days or weeks designing the optimal, abstract, DL”. This may take weeks if you are completely incompetent!!!!!!!!! I suppose you write all your code manually or use a dataset designer, AHHHH! I have written in a few hours custom CodeSmith templates to auto generate my domain objects, data layer classes, and ORM layer to be completely persistent ignorant from a database. The benefit of having such flexibility applies to unit testing with mock objects. Yes, I have heard the pathetic arguments that you can write unit tests when your objects that are tightly coupled to the database. The problems with this arise when creating and running the tests. You end up spending considerable time ensuring your database data conditions are correct for each test This often leads to abandoning writing unit tests altogether. In additional, just running the unit tests takes considerable time. By have a P.I. data layer that can be mocked with dependency injection, you can bypass this nightmare and focus on testing the business rules. I worked for many years in the financial sector and accuracy was paramount! Second issue with his statement “How often do you think the data source will be replaced”. Replacing a database is probably not likely. But adding additional disparate data sources is possible, I have seen it. Let’s not forget all the times Microsoft changes their data access… Finally, to the statement “All in all I think the pattern/design/practices discussions of today are bloated and brings very little to the table.” This is probably the most ignorant, vacuous statement that I have ever heard; my head aches and I want to shout NOOOOOO!!!! I hope I never see or use any code this guy wrote. Common sense says not too….
Left by MFS1 on Jan 08, 2009 10:50 AM

Your comment:

 (will show your gravatar)
 
Please add 6 and 7 and type the answer here: