Definition? Good Software design/architecture.

Started by
32 comments, last by Lucidquiet 18 years, 1 month ago
What is "good" software design, or "good" software architecture really? A good software architecture is said to be one that exhibits an optimal degree of fault-tolerance, backward compatibility, forward compatibility, extensibility, reliability, maintainability, availability, serviceability, usability, and such other "ilities" as necessary and/or desirable.. Now that is the most general definition ever... it describes more the possibilities of what a software system could be. What should one make of all this? Obviously there is a need for a context, after all "One should not use a cannon ball to kill a mosquito." But then how does one know if they are working on a "bad" architecture? It should be assumed that experience tends to exemplify what the best practices are, but does that neccessarily imply a good architecture? Geee, L-
"Education is when you read the fine print; experience is what you get when you don't." -Pete Seegerwww.lucid-edge.net
Advertisement
The concept of 'good' software design is very fuzzy - basically, with some experience, you'll know it when you see it.
What is a "good" building? What is a "good" car? What is a "good" anything? Evaluting the "good"ness of something is never simple.

You listed some criteria for judging the "good"ness of software. Obviously, the more the software meets the various critera you listed, the "good"er it is. What more do you need?
John BoltonLocomotive Games (THQ)Current Project: Destroy All Humans (Wii). IN STORES NOW!
[ start rant ]

I dont like when people say "you'll understand when you grow up"

its just a false lazy answer, the real answer is "you can probably understand now if I explain it fully, but the answer is very long and I am somewhat lazy, so instead you should do some trial and error, waste lots of time, and years later after many bad mistakes you will understand how it should be"

I know you can't put a book worth of answer into a forum reply but "you will understand with experience" is bad advice (in my opinion) because experience usualy comes from mistakes (or hard work). Instead one should point to articles or books or give examples (and yes, its very hard to give a none trivial example for good design and bad design).

By the way, this applies to many areas, not just software designs.

[end rant ]

Lucidquiet: Im not realy a software engineer so Im not qualified, but if you want to explore you can go to a library and search for books on the subject (you dont have to read entire book, just skim through the pages and look for ideas and examples). You can also search for Design Documents and skim through them - look for the potential problems the design solved and look at how it is modular and can be extended.
I recomend taking at least a few hours to research and explore if you are thinking of designing something big yourself. These few hours can save many many more.

When you design something try to think of more than one way to do it and compare the differenet ways. Go through all the different criterias you mentioned and try to see how the different designs match at these criterias.

As for context, this is realy your (the engineer) responsibility to understand it from the customer. If he wants a server that is always available (after you explain to him the extra problems and extra costs) you need to put big weight on reliability, fault-tolerance availability and such (for example, you now need at least one backup server and some watchdog to reset a deadlocked process). If the customer wants more of serviceability you may want the server to be controled by a nice webpage instead of ugly telnet. The context makes the difference - and its the customer job to decide (and your job to explain and make him decide).


Iftah.
I hope you don't take this the wrong way, but you likely will; indeed I would've. I used to be one of the folks who discounted experience, I mean "I know all the syntax, why can't I do the same thing other programmers can do?". It's not that easy, is it? Syntax is not design, it's not architecturing. 'So link to GoF, maybe some design pattern sites!' sure, that will help a little, but that's just higher level syntax. Without actual experience implimenting, adapting, and using the tools you'll not become skilled with them.

Yes, experience mainly involves learning from mistakes. And yes, experience won't make up for lack of skill. And yes how the professional world measures experience is quite poor. But it's still quite valuable and cannot be replaced by all the books and all the weblinks in the world.

I know, I know, you don't buy it. I didn't either. But you know what? People who gave me that advice were correct. I did understand [better] once I grew up.
I'm with Telastyn. There are many things in life which are difficult - even impossible - to explain to someone who does not have personal experience in dealing with those things. Software design is one of them. There are many nuances, subtleties, and interesting possibilities in software design; the longer I work with software (both as user and as creator) the more of this I see. Without a common basis for communication, words are meaningless; experience forms that common basis. I can debate with someone about whether a car is grey or olive green, for example. But if I hold that debate with a blind person, it's just a bunch of hollow, dead words. Without experience, color is a useless concept. This is true of many things.


As to the original question: a good design does no less and no more than is required. The hard part is figuring out what is required.

Wielder of the Sacred Wands
[Work - ArenaNet] [Epoch Language] [Scribblings]

Quote:Original post by Telastyn
I hope you don't take this the wrong way, but you likely will; indeed I would've. I used to be one of the folks who discounted experience...


No, I don't take that the wrong way...

I'm merely looking for some metrics to judge the quality of software. I'm writing a paper about Refactoring, and I sort of painted myself into a corner. The problem is that the purpose of Refactoring is to improve software while maintaining behavior (or modify the structure while preserving the behavior). But changing the structure implies a purpose (namely improved design/architecturee) but what does that mean exactly? Are the modification aimed at an architecture that is deemed adequate because of experience? Is it a matter of style, taste or aesthetics? Is it just implementing a pattern? No it's not any single one of those things. So what is improving design?

L-
"Education is when you read the fine print; experience is what you get when you don't." -Pete Seegerwww.lucid-edge.net
Sorry LucidQuiet, the 'you' in that quote was aimed more at Iftah.
Quote:Original post by Lucidquiet
What is "good" software design, or "good" software architecture really?

A good software architecture is said to be one that exhibits an optimal degree of fault-tolerance, backward compatibility, forward compatibility, extensibility, reliability, maintainability, availability, serviceability, usability, and such other "ilities" as necessary and/or desirable..

Now that is the most general definition ever...

No, it isn't. It's extremely precise.

Fault-tolerance means the system recovers from errors. Backwards compatibility means that it does not invalidate the end user's prior work or data (don't you hate upgrading an application and then not being able to read your old data, or not being able to write data in a format that users of the earlier version can read?). Forward compatibility means engineering an extensible system - a forward compatible file format, for instance, would be one that allows for new data elements to be added without invalidating the file to older versions: version N reading a version (N + x) file would simply skip the portions it doesn't understand (many chunk-based file formats can do this).

(Note that the above definitions are specific to software, but the general principles are applicable to all systems. A backward compatible piping join is one that can accept both old and new pipe sizes and threading. An excellent example of backward compatibility is my Canon d-SLR that can accept both EF and EF-S lenses, which have different locking mechanisms. That's a good design. Forward compatibility in physical systems would be the existence of connectors and data lines that allow for new peripheral attachments - the plethora of gadgets for the various iPods are due to its being much more forward compatible than competing products from Creative and iRiver.

And so forth.)

Every one of those "ilities" you disdain is a very precise definition. Remember, the purpose of jargon is to allow for denser communication - to transmit a complex idea in a very short time by using a representative term. I suggest you study what each of the stated properties of a well engineered system actually mean before you discard the definition.

Quote:Obviously there is a need for a context, after all "One should not use a cannon ball to kill a mosquito."

If it's obvious, it doesn't need to be stated, does it?

Quote:But then how does one know if they are working on a "bad" architecture? It should be assumed that experience tends to exemplify what the best practices are, but does that neccessarily imply a good architecture?

Actually, experience teaches one what generally doesn't work, or how things commonly fail - very valuable information in designing a robust and fault-tolerant system.

We design systems to solve problems, and most complex problems are composites of smaller, proportionally simpler problems. Eventually, if you drill down enough, you'll find a common problem that has been solved many times over, at which point you reference a design pattern that encodes the solution. You then closely observe the specifics of your own problem to determine whether the pattern can be applied as is or requires modification. Remember, ultimately, problems are frequently similar but seldom identical.

Happy hacking.
This may be my own personal take on refactoring, but I feel the following points are most important (some may dissagree):

1. If the source code is difficult to read (such as through poor variable or function naming) these should be reworded for clearification.

2. If a function is too long and does too many things it should be broken up into smaller parts. Functions can be similar to defining a vocabulary for your program to use. These "words" should be clearly defined and easy to reuse in multiple cases, if possible.

3. If at all possible, there should be no redundant code. There is no need to retype essentially the same code segments multiple times if point two is followed.

4. The program should be as efficient as possible while not disrupting above three points. This may involve using inline functions or improved methods of solving a problem. However, in the long run readability and maintainability may be more important than efficiency, since computers will become more powerful (although threading may need to be use more often in the future).

5. Everything should be as modular as possible. Compleatly rewriting a portion of the program (such as a class) from scratch should not in any way break other parts of the program which may rely on the part which was changed. For instance, it is not good for your source code to be a tangled mess of low-level interactions, such as directly accessing or modifying variables in an object or objects performing operations apon objects other than themselves (a class sending commands to another class is, of course, acceptable.)

I cannot really think of much more at the moment, but I hope this is helpful to you.

This topic is closed to new replies.

Advertisement