Sign in to follow this  

Definition? Good Software design/architecture.

This topic is 4296 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Recommended Posts

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-

Share this post


Link to post
Share on other sites
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?

Share this post


Link to post
Share on other sites
[ 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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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-

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
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.

Share this post


Link to post
Share on other sites
Oluseyi, I'm afraid that the definition is not extremely precise... it rather unbounded, and intended to convey that a system should have these things if "Desired" and are general enough to cover NO details.

"Fault-tolerance means the system recovers from errors." Not exactly true. Fault-tolerance may mean it does something within a certain time frame like 80% of all queries are completed in 1 second. Or the device will respond in no more than .5 seconds to such and such reading. Not just recover from errors.

The main point here is to say that if 2 different (structurally speaking) systems, implement a Fault-Tolerance requirement which has the better architecture? Because without that better architecture the system may, or may not be able to achieve the other "good" architecture attributes listed in my original post.

L-

[Edited by - Lucidquiet on March 7, 2006 12:14:08 PM]

Share this post


Link to post
Share on other sites
Quote:
Original post by Trap
Improving design:
Optimizing the length of a proof of correctness of the whole program.


NICE!!! I like this, but how does this then affect maintainability, or readablity? Improved design is more than, and possibly has nothing to do with optimization...I would have to say this is true as well... Perhaps a "good" design would better assist the compiler in optimization...hmmm... I don't know, but that is something to think about.

L-

Share this post


Link to post
Share on other sites
Quote:
Original post by Waffler
This may be my own personal take on refactoring, but I feel the following points are most important (some may dissagree):

See above for points 1-5.



Thanks for the points. I agree with the above statements. I suppose the trick that is most difficult to explain about refactoring is the human factor. There is NOT a number, like lines of code, or size of method, or number of classes, or number of fields, or this really could be done as such and such pattern, or some other pattern. A rationale could probably be given for why a refactoring could be done, but no defacto example of the architecture.

L-

Share this post


Link to post
Share on other sites
Im sorry to digress from the original thread, but I have to respond:

Telastyn, ApochPiQ:

experience is of course valuable. But refusing to teach because of lack of experience is wrong. I've had 4 years of proffessional programming experience before I started university and I know how much it helps me (especially when I see stupid bugs by other students in seconds, where they get stuck for hours), but I think learning from the trial-error experience is not the way to go. Its extreemly slow and ineffective.
Experience can come from examples not only from trial and error, and guess what, examples (if designed to be pedagogic) worth much much more because they come with tips and hints and descriptions and explainations and they are minimal and they are designed to make a point.
For examples the bug things: you can get stuck on a bug for days, debugging huge code until you find the bug and fix it. Half a year later you do the same bug and find it abit faster, just a few hours. Two years later you do the same bug again but this time you find it very fast. Instead of this process you can learn the bug from a small example (just a few lines of code) with tips and explainations and *boom* the first time you do the bug you find it and fix it in minutes (and maybe even you will never do the bug because the example is a much better teacher than trial and error).

The best selling "effective C++" teaches by examples. For examples he shows how *not* to do a string class, covering many possible errors and then shows how to do a string class. This is much better than saying "you will know how to do when you get experience" (implying try and fail until you cover all the possible mistakes).

Let me digress even farther - some people know "by intuition". They say they can't explain how they know because its intuitive for them. But there is no magical intuition and no mysticism, the intuition is the brains way of learning from examples (not from strict rules). You usually don't remember the examples but the learning gives you a "hunch" whats the better way to do things. You can get this hunch after years of experience or you can get it after a few weeks of reading proper books and examples.

ApochPiQ: I agree you cant talk to a blind about colors, but you can talk about proper design even with an unexperienced programmer (true he may misunderstand some and you will have to explain alot slower).

Telastyn: Experience can be replaced by reading books or web links, but not most books because so few out there try to give the effect of experience. I believe examples is the way to teach (after you know the basics) and with examples you can get the effect of experience. The design patterns is an excellent point - I prefer someone with 3 months experience who read the book than someone with 3 years experience who havent read the book (or other design patterns articles). Would you choose the "experienced" one to do a job for you?

Iftah.

Share this post


Link to post
Share on other sites
Quote:

Would you choose the "experienced" one to do a job for you?


All else being equal: Of course.

I could wait the week or two it takes for the experienced developer to buy and read through GoF, toying with some code. I can't wait 3 years for the inexperienced developer to 'catch up' with the other in all those little details you pickup along the way.

Share this post


Link to post
Share on other sites
Quote:
Original post by Lucidquiet
Quote:
Original post by Trap
Improving design:
Optimizing the length of a proof of correctness of the whole program.

NICE!!! I like this, but how does this then affect maintainability, or readablity? Improved design is more than, and possibly has nothing to do with optimization...I would have to say this is true as well... Perhaps a "good" design would better assist the compiler in optimization...hmmm... I don't know, but that is something to think about.

-insert Knuth quote about optimization here-

Maintainability is very strongly connected to correctness, you want to change the program either to make it correct or to extend it while keeping it correct. The easier/shorter a proof of correctness for the part of code you are changing would be, the easier you can check that the result is correct and the more likely you get it right "by accident" (without formally trying to verify it).

Readability and understandability are somewhat orthogonal to correctness and somewhat orthogonal to design too. I would argue that both depend more on the familiarity the reader has with the concepts used in the code than they depend on the code (given code reasonably named things).

Share this post


Link to post
Share on other sites
Quote:
Original post by Iftah
Im sorry to digress from the original thread, but I have to respond:


Excellent points... not that much of a digression. The point, I think if you take it to another level, is one of teaching Architecture. If architecture is NOT TAUGHT then everyone must repeat the same mistakes that experience designer/architects stumbled through. Less progress is made by the profession then.

L-

Share this post


Link to post
Share on other sites
Quote:
Original post by Iftah
Im sorry to digress from the original thread, but I have to respond:

Telastyn, ApochPiQ:

experience is of course valuable. But refusing to teach because of lack of experience is wrong.[...]
You can't blame somebody for not teaching something they don't know. Skills gained through experience are often practically impossible to teach simply because the skill is not formalized and is done mostly by intuition. Of course intuition isn't magic, but it's not understood either. That's almost the definition of intuition - the ability to know something without understanding how it is known. Trial and error is slow, but it's also the strongest way to learn a skill, and for skills that are not yet formalized, it can often be the only way to get a decent understanding of a subject.

I'd greatly appreciate any examples of people teaching such informal skills through books or the like, but to put it simply, I've been looking a long time, I have bought and read many books, and not a single one covers such skills to my satisfaction.
I have applied the trial and error system to learning from books, and software design does not appear to be sufficiently formalized at this time for a meaningful book to be written about it.

Don't get me wrong, there are plenty of good books on things like coding practices, but they don't teach software design, they teach coding practices.

The few books that actually cover software design stick to the vague terminology being complained about in this thread.

Of course, I haven't read every book on software design, but I've bought those that are highly reccomended by a variety of sources, and while they're mostly good books, they don't cover software design.

As far as my definition - software design is making a program better. Just like anything else, it means different things in different situations. On an embedded device, better might mean faster and/or using less memory. On an average business application, it might mean making the code easier to understand so future generations can maintain it. For a game engine, it might mean making the code easily extensible. Of course, those 'definitions' are also ambiguous. That's the way intuition-based skills work.

Share this post


Link to post
Share on other sites
Quote:
Original post by ExtrariusI'd greatly appreciate any examples of people teaching such informal skills through books or the like, but to put it simply, I've been looking a long time, I have bought and read many books, and not a single one covers such skills to my satisfaction.


The only thing that I can see coming close is not published yet, and probably won't be for another 2 years or so...

Architecture Handbook

L-

Share this post


Link to post
Share on other sites
Quote:
Original post by Telastyn
Quote:

Would you choose the "experienced" one to do a job for you?


All else being equal: Of course.

I could wait the week or two it takes for the experienced developer to buy and read through GoF, toying with some code. I can't wait 3 years for the inexperienced developer to 'catch up' with the other in all those little details you pickup along the way.


bah, you are cheating [smile]. I meant the exprienced one hasnt read and will not read it (its against his religion to read about patterns). The point I was trying to make is that a good book, filled with small well crafted examples is more valuable than simple blind trial-error experience. Maybe after 20 years the experienced one will know all the patterns from his experience, but wouldnt it be faster to learn from a book?

I know this GoF book isn't a full replacement for experience (to say the least). There are numerous different aspects to programming experience, ranging from typing fast to recognizing bugs to designing good software. But my point is that each and every one of these different aspects can be tought much better and faster if you dont leave it to "learn by mistakes".

My "anger" is not aimed at anyone who answered in this thread, its more at the authors of the books who say the criteria but never give examples of right and wrong. And the wrong way is importent, if you see only good examples you dont recognize when you are doing something bad. The more formal the subject the less need for wrong examples (ie. in math you dont need an example of how not to do an integeral) but when things arent defined well those with experience should teach by giving examples to give the intuitive definition to the terms.

Its a problem, I know, to fully understand a certain criteria like a professional one may need tens or hundereds of good and bad examples, which is alot of content. But I truly believe that if someone is patient enough to go through tens of good/bad examples he will understand the subject just as much as an experienced professional.

Share this post


Link to post
Share on other sites
*shrug* I've had experiences where reading a manual for an hour didn't teach nearly as much as 5 minutes of fiddling. I've had experiences where I've flailed away at some code for weeks that was made clear in a page of Design Pattern text.

Saying that book-learning is better than fiddle-learning in every scenario I think is just a little... absolute.

Share this post


Link to post
Share on other sites
Quote:
Original post by Lucidquiet
Improved design is more than, and possibly has nothing to do with optimization...I would have to say this is true as well... Perhaps a "good" design would better assist the compiler in optimization...hmmm... I don't know, but that is something to think about.


Quote:
Original post by Trap
-insert Knuth quote about optimization here-


A good design may also take optimization in account. For example, given a problem where you store a lot of information in a list. Now, consider these two designs:

*) the first one makes correct uses of design patterns, repect the OO principles and is easy to understand (I don't say easy to read, because beeing easy to read is a code attribute, not a design attribute). The genericity of the interface needs that each time you need an information you have to run through the whole list.

*) the second one is also very easy to understand, obey the major OO principles but makes a poor use of the design patters. It has shortcuts that allow you to make multiple queries and operations on a single list run-through.

So: which one is better? The very good one one that will create slow code or the less good one that will create fast code?

Share this post


Link to post
Share on other sites
Quote:
Original post by Emmanuel Deloget
A good design may also take optimization in account. For example, given a problem where you store a lot of information in a list. Now, consider these two designs:

*) the first one makes correct uses of design patterns, repect the OO principles and is easy to understand (I don't say easy to read, because beeing easy to read is a code attribute, not a design attribute). The genericity of the interface needs that each time you need an information you have to run through the whole list.

*) the second one is also very easy to understand, obey the major OO principles but makes a poor use of the design patters. It has shortcuts that allow you to make multiple queries and operations on a single list run-through.

So: which one is better? The very good one one that will create slow code or the less good one that will create fast code?
The usage of design patterns has nothing to do with good design.

That aside, let's say that the second one wasn't quite as easy to understand—given the more complicated query interface—detracting from the design somewhat. That extra complexity has, however, actually improved the design by abstracting out common usage patterns, providing ways to write new code faster and with less possibility for error.

Your optimisation in this case has improved two things: extensibility, and program execution speed. The weight of these improvements upon the goodness of the design can only be measured by whoever set the requirements.



As has been said previously, good design is all about the requirements. If you design an elegantly simple, fast, and extensible program, but leave out the ability to tally widgets—when that's a requirement—then your design is bad.

Good software design is like a good building design: it has a job to do, anything else is extra.

Share this post


Link to post
Share on other sites

This topic is 4296 days old which is more than the 365 day threshold we allow for new replies. Please post a new topic.

If you intended to correct an error in the post then please contact us.

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

Sign in to follow this