We are going to develop a strong plugin-based c++ software. There is only few source-code examples for it. Due to the big size of the project, we want to do a simple software modeling, before we start to implement it. First of all class and sequence diagramms. We are newbies to UML, due to this reason, it would be nice, to have an UML-Example for a plugin-based project. We haven't found any examples for it on the web. Design patterns we want to use are i.e. plugins, plugins manager, factory method, singleton and some others. And now my question:
Do you know a (simple) example for a UML-Project for a similar software design?
Thank you.
Cheers Alex.
I don't know about the examples of this kind, but I can suggest you a set of diagrams/views that you should probably create in this kind of project. UML is very flexible tool and software projects are so diverse in nature, that it is hard to set up rules. You should listen to your developer instinct and simply model what you need in order to go forward with the project.
So...
1- Components (mandatory)
As this is a plug-in project, there are implicite external dependencies involved. You should make a component diagram to show your future plug-in (a component) as a black-box in its environment. Another obvious component will be the base-tool (to which your komponent will be plugged-in)
- Model all relevant interfaces between parts! This is fundamental
- Use stereotypes to show the implementation platform for each component (e.g. C++)
2- Use Cases (optional)
Here you can identify your Users (Actors) and what they can do with the plug-in (use cases). An alternative would be to capture reqs using wireframe model (non UML) or something like that.
3- Conceptual views (optional)
You did not tell anything about your plug-in functional logic. How complex is it? If the plug-in logic is very complex and has many concepts, algorithm, etc. then you should consider modelling this aspect on the conceptual level. Problem concepts and their relationships are captured using class diagrams. In addition you can use state machines (for active classes), activity diagrams (for complex algorithms), sequences (relevant scenarios), etc. all on conceptual analysis level (no implementation details)
If your plug-in domain logic is trivial, you can minimize this view. Sometimes a single state machine helps or an activity diagram, etc.
4- Architecture (mandatory)
Here you can use components and/or class diagrams to show the high-level view of your plug-in internal structure. This view extens the black-box view (explained in 1-), giving a white box complement. Only main modules are shown with an accent on interfaces between them and especially towards the external world.
5- Design (optional)
Here you should be pragmatic and not do this view just to have it done. If the plug-in is not very large and you have a trained team, the Architecture view will do the job. All depending on your plug-in complexity you can decide to show one or more levels of hierarchically related view. Components are typically on the top level, including more components and/or design classes.
Note that we speak the implementation-language on this level and ALL elements should have a clear stereotype (C++, DLL, EXE, etc).
Design view should also have some behavior diagrams of choice (sequences, activities, states, etc), again on the implementation level.
Traceability
The last but not the least. All these views look at the same underlaying system from different points of view and in different stages. Therefore there are a lot of implicit or explicit dependencies and relationships between the elements in different view. You should be fully aware of them and even show some of them on separate diagrams or via traceability matrix (some tools support it). Some traces you can make between proposed views:
1->4 Black-box and the corresponding white-boxes
4->5 high-level to low-level map (a component on architecture level is implemented by classes on the design level)
2->4, 2->5 Which components/classes will participate in which use cases
2->3 a single use case logic can be further specified through some conceptual modelling
behavior diagrams are strongly related to structural elements (state machines belong to classes or components), sequence diagram includes collaborating instances of classes/components, activities can show lverall usage scenarios of components or a class's method algorithm, etc.
etc.
There are a lot of ways to do this work and nobody can give you a concrete winning formula. UML modelling should assist you in your analysis/design work, beign a natural side-product of it. If you feel that you don't know what to model or you don't see the clear purpose of a diagram - just don't do it.
As for "factory method, singleton and some others", expressed in class diagrams, read the Gang of Four book.
As for plugins, you are looking in bad places. They are to be expressed in means of component and package diagrams, not class ones.
As for sequence diagrams, (also state machines, timing, activity...) , they are not intended for showing the problems of structure. And plugin is a structural term. Behavioral diagrams are useful, but they don't have any specifics when used for plugins.
For interactions of plugins, also look for UML communication and interactions overview diagrams. And maybe look at diagrams in the book "Enterprise Integration Patterns...". Their diagrams are not UML standard ones, but IMHO, are very convenient and useful for modelling of interactions on the level of components and packages (or plugins).
Here is my small link collection for the plugin architecture topic:
C++ basic implementation
Dobbs article series for that topic with all the implementation details, c++
Microsoft article, using .net features
Implementation details considering loading dlls in c++
Related
My system uses both Augmented reality and computer vision,
The first feature is: The user actor can scan a specific object and the computer vision should recognize it.
The second feature is: The user actor can view a specific place using the augmented reality.
Each feature is a use case connected to the user, but do I also connect them to some sort of AI actors? and if so what is the suitable way to do it?
Do I just say "Computer vision system", and "Augmented reality system" ?
Feature or use-case?
This is a good start. However, there is a key misconception here:
Features are characteristics or capabilities offered by the software that are valued by users because it helps them to achieve some purpose. Features are often identified with user stories.
Use-cases represent goals of the actors using the system, that corresponds to a set of behaviors and interactions with the user, without reference to the internal structure of the system.
These a two different concepts. There is of course some overlap: some higher level capabilities can be described in terms of goals. For example, an ERP can be expected to have accounting, warehouse management and sales administration features.
But features are more general: it can also describe technical capabilities that are not directly observable by the user (e.g. backup), capabilities that are not directly related to a specific set of behaviors (e.g. multilingual user interface), Or which are much more detailed (e.g. date picking feature)
If you're on features, you may consider non-UML techniques, such as a feature tree, or user-story mapping (which is a kind of feature tree constructed with user-stories).
The big picture with use-cases
In your diagram, the bulbs seem to show that the system offers, and not what the user wants to do. If you want to show the big-picture with use-cases, you need to relate the bubbles with user goals:
Does the user just want to scan objects? Or is this scanning only one step for a larger goal, such as making an inventory, recognizing and ordering spare parts, or populating a virtual world.
Does the user just want to view a place in VR? Or are the expectations more ambitious, like purchasing products that would look fine in a given place?
This might look like an unecessary philosophic debate. But it is not. Because the main benefit of use-cases is a goal-oriented approach. Framing the problem or the expectations correctly, may allow you to think more creatively at alternatives instead of locking you early in a pre-conceived solution.
The right boundaries
The actors raise another question: are these actors autonomous and independent systems and do they matter to the user? Or are they just implementation details?
Formally, actors are external to the system, and moreover, the use-case should not depend on the internal structure of the system. So if the computer vision and the virtual reality system are in fact libraries, components, sub-systems of your system, they should not appear in the diagram.
Secondly, use-cases should offer observable result of value for actors. If the external system is dependent on your system and has no value on its own, then the use-case results cannot be of value to this system. For example, a DBMS are often viewed as candidate actors, but do not pass this test: the DBMS without the main system would be useless. If the system is not independent an autonomous, just remove it from the diagram to keep things simple.
Lastly, is, does the system actor matter to the other actors? If it makes no difference for your human users if an external system-actor intervenes, keep it simple and do not show the system-actor although you could. Because then again, it's more an implementation choice to rely on an external system than a requirement.
The way you denoted it is common practice. The so-called primary actor (which is who receives the added value from the system under consideration) is placed to the left and the so-called secondary actors (which only take part in and/or support the use case) are placed to the right. Depending on who the reader of the UC diagram will be their appearance will make sense or not. If you present it to some customer they are likely not interested in IT blurb. But for system designers it would be some important information.
For my next project I would like to try UML modeling. There are several reason - mainly documentation + to break ground for development to avoid re-coding everything over and over again.
I've tried it several times in the past, but I had a feeling like without a deep knowledge of the background libraries my work will depend on, It's not a trivial task, as at the very beginning I don't know, what kind of member variables and functions I would need.
Usually I was coding to get familiar with the libraries and API my app was interface and I get into a state, where the work was almost done or let's say it was from 50% ready, where it made no sense to me to start modeling something.
Am I true you really need to understand well the background or there are ways/techniques how to overcome this?
Another point is, do you built up the model from bottom to top or from top to bottom or it depends on the use case?
Thank you for any recommendations how to proceed.
If I understand well, your main challenge is to get an understanding of the libraries and API that you are using.
If you intend to create an UML diagram for reverse-engineering the library and understand it, you might loose your time: You'd be able to make a meaningful model only once you've understood how the pieces fit together. And for this discovery and knowledge acquisition, you already use the most effective approach:
Usually I was coding to get familiar with the libraries and API my app was interfaced.
Now, if the library or the API is delivered with an UML model, it's another story: an existing design model (not all the details of the implementation, but the core elements of the design, and interaction scenario that are difficult to grasp from the code) could help you to grasp faster how the library works, which will help you to go faster through the exploratory phase.
It's also a different story when you are reverese-engineering an undocumented app: there you don't have a tutorial, and it's difficult to write code to use the existing elements in a meaninful way. There it could make sense to document the system post-mortem. But again, do not lose yourself in a detailed implementation model with all the details: focus on the core elements, whose understanding will really matter for your maintenance fellows.
The three main purposes of making UML class models when developing an app are:
Describing the entity types of the app's problem domain for analyzing and better understanding the requirements for the app in a conceptual (domain) model.
Designing the schema of the app's underlying database (this is typically an RDB schema defined with a bunch of CREATE TABLE statements).
Designing the model classes of the data model of your app, which will be coded, e.g., as Java Entity classes or C# classes with EF annotations.
For 1 and 2, you may take a look at my book An introduction to information modeling and databases, while for 3 you may check out a book on model-based development, e.g. for Java Backend Apps or JavaScript Frontend Apps.
If your goal is to model the dependencies of your app, this may indeed be another purpose. However, as argued by #Christope, reverse-engineering a library is itself a big project that may easily consume more time than you have for developing your app.
In this article by Jakub HolĂ˝ on writing maintainable and evolvable tests, the author shares his experience of a course lectured by Kent Beck and that when designing a part of the system Kent would divide the classes into workers (containing logic and fully unit-tested) and integrators (very little logic, tested by integration tests).
Reading this I remembered an article by John Sonmez that expressed the very same idea:
What I mean by this is that our goal should be to refactor or write our code in such a way that logic is grouped into classes that only depend on primitive types and data classes, not other classes that contain logic.
This of course is not fully achievable, because something will have to tie all of these logic containing classes together. We we need these tie-together classes, but if we can make their job to simply execute commands and tie other classes together, we can feel pretty confident in not unit testing them, and we make our job a whole lot easier.
This sounds like very reasonable advice to me, but I could not find any other resources on the idea, partly because I have no idea what to search for.
Does this idea / pattern have a name?
EDIT Just found another great article by Steven Sanderson that describes the same idea. He speaks of Algorithms and Coordinators which are terms that I like a lot.
This is pretty much what "Ports & Adapters" (also known as the Hexagonal Architecture) is about.
It structures you business code into "Domain" which contains your use case independent business logic (domain entities) and "Application" which contains your use case specific business logic (application services).
In addition you have "Adapters" which implement the technical code, like integration with other services, databases, frameworks, etc.
"Ports" are the abstract declarations that adapters implement (i.e. The interface for a repository is a port, the implementation of that interface is the adapter)
The application services are, what other approaches call "Coordinator", "Interactors", or "Control Objects" (not to be confused with "Controllers").
The "Domain Entities" are what other approaches call "Algorithms" or, well, "Entities".
Kent Becks "Workers" are a combination of "Application" and "Domain", while his "Integrators" are "Adapters" in P&A speak.
(don't confuse domain entities with database entities)
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I've tried wedging my clojure diagrams into what's available in UML, using class-blocks as the file-level namespaces and dependency links to show relationships, but it's awkward and tends to discourage functional patterns. I've also tried developing ad-hoc solutions, but I can't discover a solution that works as well as UML with, say, Java (simple directed graphs seem to work in a vague manner, but this the results aren't detailed enough). Furthermore, I'm not finding anything on the web about this.
Just to be clear, I'm not trying to do anything fancy like code generation; I'm just talking about pen-and-paper diagrams mostly for my own benefit. I'm assuming I'm not the first person to have ever considered this for a lisp language.
What solutions have been proposed? Are there any commonly-used standards? What do you recommend? What tools do you use?
It depends on what you want to describe in your program.
Dependencies
Use class diagrams to model the dependencies between namespaces; in this case, it's more clear if you use packages instead of classes in a diagram.
You can also use class diagrams to model dependencies between actors
Data flow
You can also use Communication Diagrams to model the flow of data in your program. In this case, depict each namespace as an entity and each function as a method of that entity.
Or, in the case of actors, depict each actor as an entity and each message as a method.
In any case, it's not useful to try and describe the algorithm of your program in UML. In my experience, they are better described in comments in the source file.
I think its less about the language and more about your conceptual model. If you are taking a "stream processing" approach then a data-flow network diagram might be the right approach as in some of the Scheme diagrams in SICP. If you are taking a more object oriented approach (which is well supported in Lisp) then UML activity diagrams might make more sense.
My personal thought is to model the flow of the data and not the structure of the code because from what i'v seen of large(not really that large) Clojure projects the code layout tends to be really boring, with a huge pile of composeable utilities and one class that threads them together with map, redure, and STM transactions.
Clojure is very flexible in the model you choose and so you may want to go the other way around this. make the diagram first then choose the parts and patterns of the language that cleanly express the model you built.
Well, UML is deeply rooted in OO design (with C++!), so it will be very difficult to map a functional approach with UML. I don't know Clojure that well but you may be able to represent the things that resemble Java classes and interfaces (protocols?), for all the others it will be really hard.
FP is more like a series of transformations from input to output, there's no clear UML diagram for that (maybe activity diagrams?). The most common diagrams are for the static structure and the interaction between objects, but they aren't really useful for the FP paradigm.
Depending on your goal the component and deployment diagrams can be applicable.
I don't think something like UML would be a good fit for Clojure - UML is rather focused on the object oriented paradigm which is usually discouraged in Clojure.
When I'm doing functional programming I tend to think much more in terms of data and functions:
What data structures do I need? In Clojure this usually boils down to defining a map structure for each important entity I am dealing with. A simple list of fields is often enough in simple cases. In more complex cases with many different entities you will probably want to draw a tree showing the structure of your data (where each node in the tree represents a map or record type)
How do these data structures flow through different transformation functions to get the right result? Ideally these are pure functions that take an immutable value as input and produce an immutable value as output. Typically I sketch these as a pipeline / flowchart.
If you've thought through the above well enough, then converting to Clojure code is pretty easy.
Define one or more constructor functions for your data structures, and a write a couple of tests to prove they are working
Write the transformation functions bottom up (i.e. get the most basic operations working and tested first, then compose these together to define the larger functions). Write tests for every function.
If you need utility functions for GUI or IO etc., write them on demand as they are needed.
Glue it all together, testing at the REPL to make sure everything is working.
Note that you source files will typically also be structured in the sequence listed above, with more elementary functions at the top and the higher level composed functions towards the bottom. You shouldn't need any circular dependencies (that's a bad design smell in Clojure). Tests are critical - IMHO much more important in a dynamic language like Clojure than in a statically typed OOP language.
The overall logic of my code is usually the last few lines of my main source code file.
I have been wrestling with this as well. I find flow charts work great for basic functions and data. It's easy to show the data and data flow that way. Conditionals and recursion are straightforward. UML sequence/collaboration diagrams can capture some of the same info pretty well.
However, once you start using HOF, this does not work well at all.
Normal UML diagrams for packages work ok for namespaces, not that that does much.
From some browsing on net, I just understood that any framework is set of libraries provided by the framework and we can simply use those library functions to develop the application.
I would like to know more about
what is a framework with respect to C++.
How are C++ frameworks designed?
How can we use them and develop applications.
Can someone provide me some links to understand the concept of "framework" in C++
A "framework" is something designed to provide the structure of a solution - much as the steel frame of a skyscraper gives it structure, but needs to be fleshed out with use-specific customisations. Both assume some particular problem space - whether it's multi-threaded client/server transactions, or a need for air-conditioned office space, and if your needs are substantively different - e.g. image manipulation or a government art gallery - then trying to use a poorly suited framework is often worse than using none. Indeed, if the evolving needs of your system pass beyond what the framework supports, you may find your options for customising the framework itself are insufficient, or the design you adopted to use it just doesn't suit the re-architected solution you later need. For example, a single-threaded framework encourages you to program in a non-threadsafe fashion, which may be a nightmare to make efficiently multi-threaded post-facto.
They're designed by observing that a large number of programs require a similar solution architecture, and abstracting that into a canned solution framework with facilities for those app-specific customisations.
How they're used depends on the problems they're trying to solve. A framework for transaction dispatch/handling will typically define a way to list IP ports to listen on, nominate functions to be called when connections are made and new data arrives, register timer events that call back to arbitrary functions. XML document, image manipulation, A.I. etc. frameworks would be totally different.... The whole idea is that they each provide a style of use that is simple and intuitive for the applications that might wish to use them.
A big hassle with many frameworks is that they assume ownership of the applications that use them, and relegate the application to a secondary role of filling in some callbacks. If the application needs to use several frameworks, or even one framework with some extra libraries doing e.g. asynchronous communications, then the frameworks may make that very difficult. A good framework is designed more like a set of libraries that the client can control, but need not be confined by. Good frameworks are rare.
More often than not, a framework (as opposed to "just" a library or set of libraries), in OOP languages (including C++), implies a software subsystem that, among other things, supplies classes you're supposed to inherit from, overriding certain methods to specialize the class's functionality for your application's needs, in your application code. If it was just some collection of functions and typedefs it should more properly be called a library, rather than a framework.
I hope this addresses your points 1 and 3. Regarding point 2, ideally, the designers of a framework have a lot of experience designing applications in a certain area, and they "distill" their experience and skill into a framework that lets (possibly less-experienced) developers build their own applications in that area more easily and expeditiously. In the real world, of course, such ideals are not always followed.
With a tool like CppDepend you can analyze any C++ framework, reverse engineer its design in a minute, but also have an accurate idea of the overall code quality of the framework.
An application framework (regardless of language) is a library that attempts to provide a complete framework within which you plug in functionality for your specific application.
The idea is that things like web applications and GUI applications typically require quite a bit of boilerplate to get working at all. The application framework provides all that boilerplate code, and some sort of organization (typically some variation of model-view-controller) where you can plug in the logic specific to your particular application, and it handles most of the other stuff like automatically routing messages and such as needed.