tags:

views:

114

answers:

6

Many of our design decisions are based on our gut feeling about how to avoid complexity and bloating. Some of our complexity-fears are true, we have plenty of painful experience on throwing away deprecated code. Other times we learn that some particular task isn't really that complex as we though it to be. We notice for example that upkeeping 3000 lines of code in one file isn't that difficult... or that using special purpose "dirty flags" isn't really bad OO practice... or that in some cases it's more convenient to have 50 variables in one class that have 5 different classes with shared responsibilities... One friend has even stated that adding functions to the program isn't really adding complexity to your system.

So, what do you think, where does bloated complexity creep from? Is it variable count, function count, code line count, code line count per function, or something else?

+1  A: 

Encapsulation, but not in the typical way of "everything I do with a file I do by calling file.xyz()".

What I mean by encapsulation is encapsulation looking the other way - when you're modifying something, how many other things do you need to think about? What's the smallest scope that you can reduce to when working on something?

Ideally, you can reduce to a single file with less than a few hundred lines, and not have to worry about a single thing outside of that file.

kyoryu
So you are against encapsulation, layered designs and wrappers? There are used a lot in OO (not by me) :)
AareP
No, I'm in favor of them. I believe that 'the File class knows how to print, save, display, and export' tends to break encapsulation, as it combines far too many responsibilities in one place.
kyoryu
Ok, good thing I asked to confirm. :)
AareP
@AareP: Sorry, it looks like I somehow misread the question, and answered the *inverse* of the actual asked question. The answer should be that complexity comes from *lack* of encapsulation - effectively, the number of things that a given component must directly know about.
kyoryu
A: 

i think its came from your problem domain, any software project sooner or later would become bloated and complex as the new bug is found or new features needed.

at first design you will never know or understand what problems lies ahead, it is natural, and the modification to work around this problem that will make your code evolve out of initial design path and mostly we see it as complicated as it is not our initial design.

to prevent this one of the best practice would be refactoring your codes regularly, and let your codes evolve as no codes are perfect in just single iteration. you might want to read a book about refactoring, it will explain all technique to handle complexity and bloated codes.

for example: http://www.amazon.com/Refactoring-Improving-Design-Existing-Code/dp/0201485672

uray
+1  A: 

A physicist would say entropy and the second law of thermodynamics. Why should software be any different from the rest of the physical world in which it lives? And the fix is the same as is true in the non-software world: You have to expend energy in order to clean it up by thinking and refactoring.

Not very helpful on the surface, I know. It seemed to me upon reading your question that you'd like to compile a laundry list of sources that you could watch for to try to and keep a lid on complexity and bloat.

My answer says it'll never work. The second law will not be denied.

duffymo
+3  A: 

Complexity doesn't "creep from" variable count, function count or anything else in your code or models. Complexity may or may not be there. You can (attempt to) measure it by counting variables or functions, but the number of variables or functions is not the source of the complexity. This is a subtle but crucial point.

Complexity comes from two sources:

  • The problem domain that the system is addressing. Launching the space shuttle is inherently more complex than managing a video shop.
  • The chosen solution. Different models and implementations can make tackling the same problem easier or harder. This is where the skills of the developers can shine, or obscure the process.

So, think of the problem domain you work in. Is it complex? How complex? Then think of the kind of solutions you build to address the needs. Do they follow KISS principles? Are they lean and elegant?

Corollaries:

  • You cannot get rid of the problem domain's complexity by using simple solutions. That residual complexity will always be there.
  • Refactoring, as a technique that operates in the solution domain, can decrease or increase complexity. Do not assume it will decrease it. See refuctoring.
CesarGon
+1 for "refuctoring". It's a new term to me. Very funny.
duffymo
Well, of course I'm talking only for myself, but with my complex tasks I never start with complex plan.. I just arrive at complex solution.. It's like debugging, it's much easier when you are writing the program, and much harder when you are upkeeping it..
AareP
A: 

Here's how complexity creeps on you IMO. We start programming a task and at the beginning nothing is fixed. Algorithms are dynamic so we feel that all solutions and choices are possible. After few thousand lines you start to loose that sence of freedom, and notice that programming is all about designing some static system, that has real limits, and that either works for you badly or doesn't work at all. You hope that your OO design will serve exactly the task you need, but lets be honest, chances for that are pretty dim. Then you admit to yourself that you program is "bloated", and try to fix it by refactoring.

So, in the end bloating is caused by limitation of our programming techniques. We just can't write large system and still feel that freedom of choice (that we feel when starting from scratch).

EDIT:

Also Bloating is not something that just slows you down, or lowers your motivation a bit. In worst case it's something that paralyzes your decision making in such a way, that you cant write a single line of code. You notice that fixing one thing breaks ten others, and nothing you do would advance your project in any way. That's why some designs have a limit to the amount of features they can have. And after that limit is reached, it's a dead end maaan... :)

AareP
+1  A: 

Large code base complexity comes from lack of componentization. Complexity comes from the graph of dependencies between your classes. If classes are nested in components with clear boundaries, complexity is summarized by the graph of dependencies between components. If this graph is layered (Direct Acyclic Graph) the complexity of the application is enormously reduced, especially if you have hundreds of components.

Tooling such as NDepend is necessary to handle large code complexity scenarios.

I wrote a lot on the topic: Keep your code Structure Clean
Control Component Dependencies to Gain Clean Architecture
Re-factoring, Re-Structuring and the cost of Levelizing

Also, I believe that namespace is the best suited code construct to build .NET components.

Advices on partitioning code through .NET assemblies

Patrick Smacchia - NDepend dev