views:

174

answers:

4

I haven't counted but its a lot. How do i refacter a 100 function class?

This is for a website, i use to have a PageView, Backend, DB layer where PageView calls the backend, every backend public function checks if the user meets the required authority then calls the DB or any other code. It wasnt as nice as it may sound, each of them have many functions within (lets say 30+ each. Also many two liner functions in Backend calling a DB func)

A friend suggested to drop the backend class and use inheritance. The function that requires mod privileges goes into ModUser which inherits from NormalUser which is nice and i now only check if the user is authorize once instead of many times (the result is only fetch from the db the first time so speed didnt improve).

The problem is now i have a large class now that i decided DB should be part of it since it doesnt make sense when theres no backend middleman. The functions are something like

  • DoPageXYZ (20 of these)
  • IsXYZUser (properties for permissions. A page with normal access can had mod bonuses)
  • getUserBlah (favourites, media, followers, comment for a page, etc)

Coding isnt difficult and is actually pretty nice but it doesnt feel right. Its weird looking through dozens of functions in one class and sometimes takes more then a few seconds to find the correct one.

How do i cleanup the class? I notice i use a MANY functions only once or twice but its often like that for my well design classes as well. Does anyone know what problem i fell into?

+1  A: 

Have a look at ReSharper as this will greatly aid the refactoring processes. I would still suggest separating like functions into their own class files if for nothing other than organistation. This will make the code more human readable and easier to maintain.

Dave Anderson
read the comment i left in Luhmann answer.
acidzombie24
@acidzombie24 You say 'hide functions in a per file level' by file do you mean class? Do you want a Page base class and that you inherit from for specific subtypes? Some may disagree but if you just want to 'hide' functions from view within the class file put in a region statement and collapse the region; http://www.codinghorror.com/blog/2008/07/the-problem-with-code-folding.html
Dave Anderson
+2  A: 

The book "Working effectively with Legacy Code" has helped me a lot in similar situations. (http://www.amazon.com/s?field-isbn=0131177052)

Patrick
Unfortunately it isnt Legacy Code. Its my current 5month old project i decided to rewrite. Does this book apply? (I am not asking if its useful, just if it targets this situation?)
acidzombie24
Do you have unit tests that cover this class? If the answer is "no", than what Michael Feathers [writer of the book] is concerned, you are dealing with legacy code (And I agree).
Steven
@Steven: The problem is input comes from outside of code. I have no idea why % encoded in a url causes a bad input and etc. So i cant unit code what i dont understand and what may change outside of my power (i dont know if IIS will handle certain things differently). The other part i do have test for but not unit test per say. Scrap functions which are sometimes put into static constructors. I really should learn how to unit test in visual studio. Or at least create a dummy project.
acidzombie24
From the book: "nearly every system ever produced suffers from slow, debilitating rot. The rot is so pervasive that we have a special name for rotten programs. We call them: Legacy Code."In your case, look at chapter 20: The Class is too big and I don't want it to get any bigger.
Patrick
+5  A: 

Its a very good idea to read a book about refactoring as suggested and get a good understanding of the SOLID principles. And do one step at a time.

You should probably as a first step refactor to a class composited of classes with only one responsibility each: Security, Pageconstruction, repository (db) ...etc. So try to identitify which different logical tasks the class does and create a class for each. So you honor the single responsibility principle, and favor composition over inheritance :)

Luhmann
+1 for mentioning SOLID
Kane
What i image happening is instead of PageName() i'll write Page.PageName but now i'll have to pass in security, urlhelper, etc into new Page(). which divides the code but creates more text/code/reading overhead and doesnt really separate it
acidzombie24
@acidzombie24: dividing code such that you have to pass objects in to newly partitioned parts is the essence of the loose coupling that separating them provides. The key point is that when you pass in that object, it can be *any* implementation that matches the declared contract. In your example, that would mean you were free to change the `security`, `urlhelper` implementations easily, and reuse and testing of the `Page` class becomes much easier. HTH.
Grundlefleck
@Grundlefleck: The problem is all the code i can think of to break up all need the other classes so i am not actually removing the functions just making it more obscure by putting them behind a class which can see as much as the original did (but by going through more objects). The solution i thought is to hide functions in a per file level but unfortunately i cant do it which would have been perfect. In C++ i could but not in C#.
acidzombie24
@acidzombie24: it's usually not necessary to hide *functions*, instead what you want to do is hide the *detail*. That way the implementation detail can hide behind the abstraction, so that change can happening without affecting the other classes. If you still find you have 100 functions, and all they do is delegate to a smaller class, maybe you would prefer to inline the function wherever it's called. Or am I still missing the point?
Grundlefleck
A: 

Read the book Clean Code: A Handbook of Agile Software Craftsmanship by Robert Martin. The readability of my code has improved big time after reading it. After reading Clean Code, start reading Working effectively with Legacy Code as Patrick notes.

Steven