class diagram for C++ - c++

Guys ! I understood that my previous question did not meant to you guys as per my intentions. I apologize for the same.
Let me pose in a different way.
Take my case, yesterday I faced an interview.
The guy out there asked me that he is trying to develop an application similar to google maps for his windows mobile device.
He asked me to come up with a class diagram for the application.
It was like a bouncer for me.
In such cases, what should be my approach ? where should I start ? How should I look at the problem ?
I hope this is better understood.
I request you to answer me considering that I am an amateur C++ developer who has never worked on any projects from the analysis & design phase
and doesn't know abc's of design.
Thanks,
krisssam

Maybe a bit overkill for an interview, but even there I would still go for 1 and 3 and start with 4.
ask as much specifications as possible, so you know what is expected
When possible/needed, make use cases to get a clear view on how it will be used
Start high level, focus on the main features. Look for preferably less than 6 players (modules) and try to see how they interact. Define responsabilites and interfaces.
Break up these players in submodules and see how these interact (also define responsabilites and interfaces). Repeat until you have implementable entities (classes)
in parallel with 4, for architecture, see how it will be deployed and what language/frameworks/libraries are needed/available.
For google-maps, I assume that players could be the map-database, the map-viewer, the user-input, the search-engine, but I'm not a GUI/GIS/mobile expert.

First you need a clear understanding about what you should be written. Formulate that understanding in English. Now every noun is a candidate for a class. Every verb is a candidate for a method. and nouns that appear in the same sentence are candidates for association.
This sounds quite simple. That's because I simplified it a lot. Actually there is much more to it. Getting a clear understanding about what should be written alone is challenging. If you are interested I suggest reading a book on object oriented analysis and design.

Define the responsibilities that each component of the software will have, then flesh classes around those.

It doesn't relate to the language.
Class diagram - means you need to identify the major objects that "plays" in this app.
The map object and it's data members and actions
the icon objects and it's data members and actions ect...

Related

How to select the right architectural/design patterns

I am doing my own research project, and I am quite struggling regarding the right choice of architectural/design patterns.
In this project, after the "system" start, I need to do something in background (tasks, processing, display data and so on) and at the same be able to interact with the system using, for example, keyboard and send some commands, like "give me status of this particular object" or "what is the data in this object".
So my question is - what software architectural/design patterns can be applied to this particular project? How the interraction between classes/objects should be organized? How should the objects be created?
Can, for example, "event-driven architecture" or "Microkernel" be applied here? Some references to useful resources will be very much appreciated!
Thank you very much in advance!
Careful with design patterns. If you sprinkle them throughout your code hoping that everything will work great, you'll soon have an unreadable, boilerplate full mess. They are recipes, not solutions.
My advice to you is pick a piece of paper and a pencil and start drawing all the entities of your domain, with all their requisites, and see how they relate. If you want to get somewhat serious about it, you can do something like this.
When defining your entities, strive for high cohesion and loose coupling.
High cohesion means that you should keep similar functionalities together. In a very simple example, if you have a class that reads stuff from a file and processes it, the class has low cohesion, since reading and processing are two very distinct functionalities. In this case, you would want a class for each functionality.
As for loose coupling, it means that your entities should be independent of each other. Using the example above, supposed that you are now the proud owner of two highly cohesive classes - one that reads stuff from a file (Reader), and one that processes that stuff (Processor). Now, suppose that the Processor class has an instance of the Reader class, and calls it in order to get its input. In this case, we can say that both classes are tightly coupled, since Processor won't work without Reader. In the OOP world, the solution for this is typically the use of interfaces. You can find a neat example here.
After defining an initial model of your domain and gathering as much knowledge about it as you can, you can now start to think about the implementation's architecture. This is were you can start thinking about the architectural patterns. Event driven architecture, clean architecture, MVP, MVVM... It will all depend on your domain. It is your job to know which pattern will fit best. Spoiler alert: this can be extremely hard to do correctly even for experienced engineers, so don't be afraid to fail.
Finally, leave the design patterns for the implementation stage. Their use completely depends on your implementation problems and decisions. Also, DON'T FORCE THEM. Ideally, you will solve a problem and, IF APPLICABLE, you'll see a pattern emerging. Trust me, the last thing you want is to have a case of design patternitis. Anyway, if you need literature on patterns, I totally recommend this book. It's great no matter your level as an engineer.
Further reading:
SOLID principles
Onion Architecture
Clean architecture
Good luck!
You have a background task, and it can be used for a message pump/event queue indeed. Then your foreground task would send requests to this background thread and asynchronously wait for the result.
Have a look at the book "Patterns for Parallel Programming".
It is much better if you check a book for Design Patterns. I really like this one.
For example, if you need to get some data from a particular object, you may need the Observer Pattern to work for you and as soon as the object has the data, you (or another object) get to know this data and can work with it, with another pattern (strategy might work, it really depends on what you have to do).
If you have to do some things at the same time, check also the Singleton pattern (well, check the most important ones!).

Secret to achieve good OO Design [closed]

Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 4 years ago.
Improve this question
I am a c++ programmer, and I am looking forward to learning and mastering OO design.I have done a lot of search and as we all know there is loads of material, books, tutorials etc on how to achieve a good OO design. Of course, I do understand a good design is something can only come up with loads of experience, individual talent, brilliance or in fact even by mere luck(exaggeration!).
But sure it all starts off with a solid beginning & building some strong basics.Can someone help me out by pointing out the right material on how to start off this quest of learning designing right from the stage of identifying objects, classes etc to the stage of using design patterns.
Having said that I am a programmer but I have not had a experience in designing.Can you please help me take someone help me out in this transition from a programmer to a designer?
Any tips,suggestions,advice will be helpful.
[Edit]Thanks for the links and answers, I need to get myself in to that :) As i mentioned before I am a C++ programmer and I do understand the OO basic concepts as such, like inheritance, abstraction, polymorphism, and having written code in C++ do understand a few of the design patterns as well.what i dont understand is the basic thought process with which one should approach a requirement. The nitty grittys of how to appraoch and decide on what classes should be made, and how to define or conclude on relationships they should have amongst themselves.Knowing the concepts(t some extent) but not knowing how to apply them is the problem i seem to have :( Any suggestions about that?
(very) Simple, but not simplist design (simple enough design if you prefer) : K.I.S.S.
Prefer flat hierarchies, avoid deep hierarchies.
Separation of concerns is essential.
Consider other "paradigms" than OO when it don't seem simple or elegant enough.
More generally : D.R.Y. and Y.A.G.N.I help you achieve 1.
There is no secret. It's sweat, not magic.
It's not about doing one thing right. It's balancing many things that must not go wrong. Sometimes, they work in sync, sometimes, they work against each other. Design is only one group of these aspects. The best design doesn't help if the project fails (e.g. because it never ships).
The first rule I'd put forward is:
1. There are no absolutes
Follows directly from the "many things to balance. D.R.Y., Y.A.G.N.I. etc. are guidelines, strictly following them cannot guarantee good design, if followed by the letter they may make your project fail.
Example: D.R.Y. One of the most fundamental principles, yet studies show that complexity of small code snippets increases by a factor of 3 or more when they get isolated, due to pre/post condition checking, error handling, and generalization to multiple related cases. So the principle needs to be weakened to "D.R.Y. (at least, not to much)" - when to and when not is the hard part.
The second rule is not a very common one:
2. An interface must be simpler than the implementation
Sounds to trivial to be catchy. Yet, there's much to say about it:
The premise of OO was to manage program sizes that could not be managed with structured programming anymore. The primary mechanism is to encapsulate complexity: we can hide complexity behind a simpler interface, and then forget about that complexity.
Interface complexity involves the documentation, error handling specifications, performance guarantees (or their absence), etc. This means that e.g. reducing the interface declaration by introducing special cases isn't a reduction in complexity - just a shuffle.
3-N Here's where I put most of the other mentions, that have been explained already very well.
Separation of Concerns, K.I.S.S, SOLID principle, D.R.Y., roughly in that order.
How to build software according to these guidelines?
Above guidelines help evaluating a piece of code. Unfortunately, there's no recipe how to get there. "Experienced" means that you have a good feel for how to structure your software, and some decisions just feel bad. Maybe all the principles are just rationnalizaitons after the fact.
The general path is to break down a system into responsibilities, until the individual pieces are managable.
There are formal processes for that, but these just work around the fact that what makes a good, isolated component is a subjective decision. But in the end, that's what we get paid for.
If you have a rough idea of the whole system, it isn't wrong to start with one of these pieces as a seed, and grow them into a "core". Top-down and bottom-up aren't antipodes.
Practice, practice, practice. Build a small program, make it run, change requirements, get it to run again. The "changing requirements" part you don't need to train a lot, we have customers for that.
Post-Project reviews - try to get used to them even for your personal projects. After it's sealed, done, evaluate what was good, what was bad. Consider the source code was thrown away - i.e. don't see that sessison as "what should be fixed?"
Conway's Law says that "A system reflects the structure of the organizaiton that built it." That applies to most complex software I've seen, and formal studies seem to confirm that. We can derive a few bits of information from that:
If structure is important, so are the people you work with.
Or Maybe structure isn't that important. There is not one right structure (just many wrong ones to avoid)
I'm going to quote Marcus Baker talking about how to achieve good OO design in a forum post here: http://www.sitepoint.com/forums/showpost.php?p=4671598&postcount=24
1) Take one thread of a use case.
2) Implement it any old how.
3) Take another thread.
4) Implement it any old how.
5) Look for commonality.
6) Factor the code so that commonality is collected into functions. Aim for clarity of code. No globals, pass everything.
7) Any block of code that is unclear, group into a function as well.
8) Implement another thread any old how, but use your existing functions if they are instant drop-ins.
9) Once working, factor again to remove duplication. By now you may find you are passing similar lumps of stuff around from function to function. To remove duplication, move these into objects.
10) Implement another thread once your code is perfect.
11) Refactor to avoid duplication until bored.
Now the OO bit...
12) By now some candidate higher roles should be emerging. Group those functions into roles by class.
13) Refactor again with the aim of clarity. No class bigger than a couple of pages of code, no method longer than 5 lines. No inheritance unless the variation is just a few lines of code.
From this point on you can cycle for a bit...
14) Implement a thread of use case any old how.
15) Refactor as above. Refactoring includes renaming objects and classes as their meanings evolve.
16) Repeat until bored.
Now the patterns stuff!
Once you have a couple of dozen classes and quite a bit of functionality up and running, you may notice some classes have very similar code, but no obvious split (no, don't use inheritance). At this point consult the patterns books for options on removing the duplication. Hint: you probably want "Strategy".
The following repeats...
17) Implement another thread of a use case any old how.
18) Refactor methods down to five lines or less, classes down to 2 pages or less (preferably a lot less), look for patterns to remove higher level duplication if it really makes the code cleaner.
19) Repeat until your top level constructors either have lot's of parameters, or you find yourself using "new" a lot to create objects inside other objects (this is bad).
Now we need to clean up the dependencies. Any class that does work should not use "new" to create things inside itself. Pass those sub objects from out side. Classes which do no mechanical work are allowed to use the "new" operator. They just assemble stuff - we'll call them factories. A factory is a role in itself. A class should have just one role, thus factories should be separate classes.
20) Factor out the factories.
Now we repeat again...
21) Implement another thread of a use case any old how.
22) Refactor methods down to five lines or less, classes down to 2 pages or less (preferably a lot less), look for patterns to remove higher level duplication if it really makes the code cleaner, make sure you use separate classes for factories.
23) Repeat until your top level classes have an excessive number of parameters (say 8+).
You've probably finished by now. If not, look up the dependency injection pattern...
24) Create (only) your top level classes with a dependency injector.
Then you can repeat again...
25) Implement another thread of a use case any old how.
26) Refactor methods down to five lines or less, classes down to 2 pages or less (preferably a lot less), look for patterns to remove higher level duplication if it really makes the code cleaner, make sure you use separate classes for factories, pass the top level dependencies (including the factories) via DI.
27) Repeat.
At any stage in this heuristic you will probably want to take a look at test driven development. At the very least it will stop regressions while you refactor.
Obviously, this is a pretty simple process, and the information contained therein shouldn't be applied to every situation, but I feel like Marcus gets it right, especially with regards to the process one should use to design OO code. After a while, you'll start doing it naturally, it'll just become second nature. But while learning to do so, this is a great set of steps to follow.
As you said, there is nothing like experience. You can read every existing book on the planet about this, you'll still not as good as if you practice.
Understanding the theory is good, but in my humble opinion, there is nothing like experience. I think the best way to learn and understand things completely is to apply them in some project(s).
There you'll face difficulties, you'll learn to solve them, sometimes perhaps with a bad solution : but still you'll learn. And if at any time something bothers you and you can't find how to solve it nicely, we'll be here on SO to help you ! :)
I can advice you the book "Head First Design Patterns" (search Amazon). It is a good starting point, before seriously diving into the gang of fours' bible, and it shows design principles and the most used patterns.
In a nutshell : Code, criticize, look for a well-known solution, implement it, and back to first step till you're (more or less) satisfied.
As often, the answer to this kind of question is : it depends. And in that case, it depends how you learn things. I'll tell you what work for me, for I face the very problem you describe, but it won't work with everybody and I would not say it's "the perfect answer".
I begin coding something, not too simple, not too complex. Then, I look at the code and I think : all right, what is wrong ? For that, you can use the first three "SOLID principles" :
Single responsibility (are all your classes serving a unique purpose ?)
Open/Close principle (if you want to add a service, your classes can be extended with inheritance, but there is no need to alter the basic functions or your current classes).
Liskov Substitution (all right, this one I can't explain simply, and I'd advise reading about it).
Don't try to master those and understand everything about them. Just use them as guideline to criticize your code. Think chiefly about "what if I want to do this now ?". "What if I work for a client, and he wants to add this or that ?". If your code is perfectly adaptable to any situation (which is almost impossible), you might have reached a very good design.
If it's not, consider a solution. What would you do ? Try to come with an idea. Then, read about design patterns and find one that could answer your problem. See if it matches your idea - often, it's the idea you had, but better expressed and developped. Now, try to implement it. It's going to take time, you'll often fail, it's frustrating, and that's normal.
Design is about experience, but experience is acquired by criticizing your own code. That's how you'll understand design, not as a cool thing to know, but as the basis for a solid code. It's not enough to know "all right, a good code has that and that". It's much better to have experienced why, to have failed and see what whas wrong. The trouble with design pattern is that they are very abstract. My method is a way (probably not the only one nor the best) to make them less abstract to you.
No-solo-work. Good designs are seldom created by a single person only. Talk to your colleagues. Discuss your design with others. And learn.
Don't be too smart. A complex hierarchy with 10 levels of inheritance is seldom a good design. Make sure that you can clearly explain how your design works. If you can't explain the basic principles in 5 minutes, your design is probably too complex.
Learn tricks from the masters: Alexandrescu, Meyers, Sutter, GoF.
Prefer extensibility over perfection. Source code written today will be insufficient in 3 years time. If you write your code to be perfect now, but inextensible, you will have a problem later. If you write your code to be extensible (but not perfect), you will still be able to adapt it later.
The core concepts in my mind are:
Encapsulation - Keep as much of you object hidden from both the prying eyes and sticky fingers of the outside world.
Abstraction - Hide as much of the inner workings of you object from the simple minds of the code that needs to use your objects
All the other concepts such as inheritance, polymorphism and design patters are about incorporating the two concepts above and still have objects that can solve real world problems.

How do you understand a large chunk of code?

I am a fresh college grad student that just started my job. In my ramp up period, I need to learn a lot of product code. There are some design docs but they do not help much.
Can you provide some general techniques to browse and understand huge product code (specifically C++)?
Run it through doxygen. This will generate html documentation which will be helpful even if the code does not have proper doxygen-style comments.
Another good advice is to look through the unit tests, if there are any. If there are no unit tests, a good way to understand the code is to write your own unit tests. The effort to do this will pay for itself many times over.
Use every method available to you (in no particular priority):
Use the product itself and understand what it does
Talk to the devs that maintained it or have worked with it previously
Debug through it and see how data flows and how classes interact ("when I click this button, what exactly happens, who is responsible?")
Look at architecture, UML, or class diagrams
One of my favorites: create your own diagrams of class hierarchies, class interactions, general control flow, high-level components, process/DLL interactions, object lifetimes and management
If they're not totally out-of-date, read the dev/test/user specs (goes well with #1)
Read the documentation on it
Most of all: be tenacious and persistent. If you don't put in the work, don't expect to understand it. If you don't understand something, dig and dig until you do. Software is not magic, it's just hard work :)
Some people will tell you to start with the data structures, but in a large system even that's not terribly helpful much of the time. I can think of four major points:
Take your time. Often, it's more like a whole series of gestalt shifts than it is a single, linear, gradual understanding. So be patient.
No matter how big it is, you should be able to put a breakpoint in and walk it in a debugger. Even in a large, complicated, multi-threaded system, you should be able walk through and see what's happening.
Ask for bugs, and start fixing them, no matter how crazy they seem. It's akin to dropping yourself into a foreign country; you'll pickup the language eventually.
Find a mentor. A jungle guide is invaluable.
I think there have been a few good responses already. My 2c worth...
Not sure what you class as huge (10 KLOC, 1000 KLOC, 10000 KLOC, etc), but one would hope that this is broken down in some way and is not a monolithic single program. Perhaps your management has some guidance on which 'module(s)' you are most likely to be spending time in at the moment. Hopefully this can help break down the problem scope.
Firstly, before you try to understand the code try to understand the product. What does it do? Then how does it do it? What does it interact with? Then how does it interact? etc...
When getting to the code try to understand the high level design and philosophy first, and work on the breadth before the depth. I agree with some of the above re fixing some bugs, but I also strongly suggest you continue to get a handle on the high level even if you need to get into the details to fix some bugs.
I also agree with the above in terms of generating some diagrams for yourself if you can't find any already in existence. And then share them, perhaps a team/product wiki? I'm curious as to why the existing doco does not help very much. Typically this is because this type of doco was generated from the early concepts and the product no longer bears any similarity, but if this is not the case then what can you contribute to this issue. One assumes that where you are today someone else will be in short enough order, and you are in an ideal position to know what essential doco is missing!
If the product is actually 'huge' then you have to accept that you will never be able to hold all of it in your head, so the best thing you can do is be familiar enough to know where to start looking (comes back to understanding the product, and approaching code breadth first).
This is obviously a pretty common question, and it's similar to this one (and the questions related to it): How to understand the design and code flow of any product quickly?
Dig through some of those answers / comments, for starters. Else, we'll just end up repeating them. :)

Presenting MVC to Old C++ Spaghetti Coders?

I wish to present the idea of MVC to a bunch of old C++ spaghetti coders (at my local computer club).
One of them that has alot of influence on the rest of the group seems to finally be getting the idea of encapsulation (largely due in part to this website).
I was hoping that I could also point him in the right direction by showing him Model View Controller, but I need to do it in a way that makes sense to him, as well as it probably needs to be written in C/C++!
I realize that MVC is a very old architectural pattern so it would seem to me that there should be something out there that would do the job.
I'm more of a web developer, so I was wondering if anybody out there who is a good C/C++ coder could tell me what it is that made the MVC light switch turn on in your head.
Don't start off with MVC. Start off with Publish / Subscribe (AKA the "listener" pattern).
Without the listener pattern fully understood, the advantages of MVC will never be understood. Everyone can understand the need to update something else when something changes, but few think about how to do it in a maintainable manner.
Present one option after another, showing each option's weaknesses and strengths: making the variable a global, merging the other portion of code into the variable holder, modifying the holder to directly inform the others, and eventually creating a standard means of registering the intent to listen.
Then show how the full blown listener can really shine. Write a small "model" class and add half a dozen "listeners" and show how you never had to compromise the structure of the original class to add "remote" updates.
Once you get this down, move the idea into to the "model view" paradigm. Throw two or three different views on the same model, and have everyone amazed on how comparatively easy it is to add different views of the same information.
Finally discuss the need to manage views and update data. Note that the input is partially dependent on items which are not in the view or the model (like the keyboard and mouse). Introduce the idea of centralizing the processing where a "controller" needs to coordinate which models to create and maintain in memory, and which views to present to the user.
Once you do that, you'll have a pretty good introduction to MVC.
You might find it easier to sell them on the Document/View or Document/Presenter patterns. MVC was invented on Smalltalk where everything about the different UI elements had to be coded by the developer (as I understand, never used the thing). Thus the controller element was necessary because didn't have things like TextElement::OnChange. Now days, more modern GUI API's use Document/View but Document/Presenter is something I've seen proposed.
You might also consider reading Robert Martin's article on the TaskMaster framework.
You might also consider that any C++ developer who is not familiar with these patterns and already understands their purpose and necessity is either a complete newb or a basket-case best avoided. People like that cause more harm than good and are generally too arrogant to learn anything new or they already would have.
Get some spaghetti C++ code (theirs?), refactor it to use MVC, and show them what advantages it has, like easier unit testing, re-use of models, making localized changes to the view with less worry, etc.

How specific to get on design document?

I'm creating a design document for a security subsystem, to be written in C++. I've created a class diagram and sequence diagrams for the major use cases. I've also specified the public attributes, associations and methods for each of the classes. But, I haven't drilled the method definitions down to the C++ level yet. Since I'm new to C++ , as is the other developer, I wonder if it might not make sense go ahead and specify to this level. Thoughts?
edit: Wow - completely against, unanimous. I was thinking about, for example, the whole business about specifying const vs. non-const, passing references, handling default constructor and assigns, and so forth. I do believe it's been quite helpful to spec this out to this level of detail so far. I definitely have gotten a clearer idea of how the system will work. Maybe if I just do a few methods, as an example, before diving into the code?
I wouldn't recommend going to this level, but then again you've already gone past where I would go in a design specification. My personal feeling is that putting a lot of effort into detailed design up-front is going to be wasted as you find out in developing code that your guesses as to how the code will work are wrong. I would stick with a high-level design and think about using TDD (test driven development) to guide the low-level design and implementation.
I would say it makes no sense at all, and that you have gone too far already. If you are new to C++ you are in no position to write a detailed design document for a C++ project. I would recommend you try to implement what you already have in C++, learn by the inevitable mistakes (like public attributes) and then go back and revise it.
Since you're new, it probably makes sense not to drill down.
Reason: You're still figuring out the language and how things are best structured. That means you'll make mistakes initially and you'll want to correct them without constantly updating the documentation.
It really depends on who the design document is targeted at. If it's for a boss who is non-technical, then you are good with what you have.
If it's for yourself, then you are using the tool to help you, so you decide. I create method level design docs when I am creating a project, but it's at a high level so I can figure out what the features of the various classes should be. I've found that across languages, the primary functionalities of a class have little to do with the programming language we are working in. Some of the internal details and functions required certainly vary due to the chosen language, but those are implementation details that I don't bother with during the design phase.
It certainly helps me to know that for instance an authorization class might have an authenticate function that takes a User object as a parameter. I don't really care during design that I might need an internal string md5 function wrapper to accomplish some specific goal. I find out about that while coding.
The goal of initial design is to get organized so you can make progress with clarity and forethought rather than tearing out and reimplementing the same function 4 times because you forgot some scenario due to not planning.
EDIT: I work in PHP a lot, and I actually use PhpDoc to do some of the design docs, by simply writing the method signature with no implementation, then putting a detailed description of what the method should do in the method header comments. This helps anyone that is using my class in the future, because the design IS the documentation. I can also change the documentation if I do need to make some alterations while coding.
I work in php4 a lot, so I don't get to use interfaces. In php5, I create the interface, then implement it elsewhere.
The best way to specify how the code should actually fit together is in code. The design document is for other things that are not easily expressed in code. You should use it for describing the actual need the program fills, How it interacts with users, what the constraints are in terms of hardware and operating systems. Certainly describe the overall architecture of your application in a design document, but, for instance, the API should actually be described in the code that exposes the API.
You have already gone far enough with the documentation part. As you still a beginner in C++, when you would understand the language, you might want to change the structure of your program. Then you would have to do changes in the documentation. I would suggest that you have already gone too far with the documentation. No need to drill more into it
Like everyone else says, you've gone way past where you need to go with the design. Do you have a good set of requirements to the simple true/false statement level that you derived that design from? You can design all day long, but if you don't have requirements that simply say WHAT you're going to do, it doesn't matter how good your design is.