Skip to content
This repository was archived by the owner on Dec 29, 2022. It is now read-only.

Commit 655ea60

Browse files
committed
Big cleanup of section names; added Search-only pages; big overall cleanup of docs and style.
1 parent de6ca7a commit 655ea60

14 files changed

+109
-73
lines changed

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ It forces an intuitive (albeit unusual) programming paradigm that results in hig
1010

1111
This is not an officially supported Google product.
1212

13+
[Full online documentation](https://google.github.io/detectorgraph/).
14+
1315
Note that the cross-reference links in this page are only rendered in the Doxygen version of the documentation (see [Building](#building)).
1416
You can also navigate the web version of the documentation hosted at https://google.github.io/detectorgraph/.
1517

@@ -144,10 +146,15 @@ Some of its most unique features are:
144146
- Flat design - the graph has only two types of constructs; Topics and Detectors.
145147
- Small & Simple - it doesn't do anything else.
146148

149+
## Style & Tips
150+
151+
For an article containing a set of guidelines & rules of thumb that we accumulated after 3+ years of using DetectorGraph visit [Style Tips - Patterns, Anti-Patterns & Suggestions](@ref ssg-style_suggestions).
152+
These are aimed at keeping software design constrained in a way that best takes advantage of the DetectorGraph framework, its expressibility and modeling power.
153+
147154
## Naming
148155

149156
The DetectorGraph library had a little naming problem growing up. From birth it came to replace nlDetectorGraph and so it pretended to be called that way. As an adolescent it decided it wanted to be called MarkII.. but no one cared - for years now the world continues to call it simply DetectorGraph. Now as it approaches adulthood it has finally accepted its popular name: DetectorGraph.
150157

151158
## In-depth Docs & API Reference
152159

153-
For in depth documentation of the library, [start here](@ref core_introduction) - these are provided by the [auto-generated docs](https://google.github.io/detectorgraph/).
160+
For in depth documentation of the library, [start here](@ref core_introduction).

doxygen/DoxygenLayout.xml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,12 +4,14 @@
44
<navindex>
55
<tab type="mainpage" visible="yes" title=""/>
66
<tab type="user" url="core_introduction.html" title="Source Code Introduction"/>
7-
<tab type="pages" visible="yes" title="" intro=""/>
7+
<tab type="pages" visible="yes" title="Discussion Topics" intro=""/>
8+
<!--
89
<tab type="modules" visible="yes" title="" intro=""/>
910
<tab type="namespaces" visible="no" title="">
1011
<tab type="namespacelist" visible="no" title="" intro=""/>
1112
<tab type="namespacemembers" visible="no" title="" intro=""/>
1213
</tab>
14+
-->
1315
<tab type="classes" visible="yes" title="">
1416
<tab type="classlist" visible="yes" title="" intro=""/>
1517
<tab type="classindex" visible="$ALPHABETICAL_INDEX" title=""/>

doxygen/core_introduction.dox

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,8 +3,9 @@ namespace DetectorGraph
33

44
/**
55
@page core_introduction Source Code Introduction
6+
@brief A general walk-through the classes that make up the framework.
67

7-
\b DetectorGraph: Formal C++ applications with logic/data separation, automatic dependency injection and data passing.
8+
\par "Formal C++ applications with logic/data separation, automatic dependency injection and data passing" — DetectorGraph
89

910
The Framework's main parts are:
1011

doxygen/custom_examples.dox

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -26,28 +26,50 @@ Below are a number of examples showcasing different aspects & usage patterns of
2626
// The list of pages below is used to help the search utility finding appropriate content.
2727

2828
/**
29-
@page loops Loops
29+
@page seo-loops Loops
3030
Loops are implemented using either DetectorGraph::Lag or DetectorGraph::FuturePublisher
3131
For examples, see @ref feedback-loops
3232
*/
3333

3434
/**
35-
@page fb-loops Feedback Loops
36-
@copydoc loops
35+
@page seo-fb-loops Feedback Loops
36+
@copydoc seo-loops
3737
*/
3838

3939
/**
40-
@page cycles Cycles
41-
@copydoc loops
40+
@page seo-cycles Cycles
41+
@copydoc seo-loops
4242
*/
4343

4444
/**
45-
@page named-topicstates Named TopicStates
45+
@page seo-named-topicstates Named TopicStates
4646
Named TopicStates are TopicStates that override DetectorGraph::TopicState::GetId.
4747
For an examples, see [this example](@ref trivialvendingmachine.cpp)
4848
*/
4949

5050
/**
51-
@page public-topicstates Public TopicStates
52-
@copydoc named-topicstates
51+
@page seo-public-topicstates Public TopicStates
52+
@copydoc seo-named-topicstates
5353
*/
54+
55+
/**
56+
@page seo-initial-state Initial States
57+
A discussion about Initial States is available on @ref ssg-initial-states .
58+
And an example is provided in @ref ex-rg-state-persistence
59+
*/
60+
61+
/**
62+
@page seo-public-initial-state Public Initial States
63+
@copydoc seo-initial-state
64+
*/
65+
66+
/**
67+
@page seo-resume-state Resume State
68+
A discussion about resuming state is available on @ref ssg-resuming-state .
69+
Full Example: @ref ex-rg-state-persistence
70+
*/
71+
72+
/**
73+
@page seo-state-persistence State Persistence
74+
@copydoc seo-resume-state
75+
*/

doxygen/style_suggestions.dox

Lines changed: 25 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
/**
2-
@page style_suggestions Style, Patterns, Anti-Patterns & Suggestions
2+
@page ssg-style_suggestions Style Tips - Patterns, Anti-Patterns & Suggestions
33

44
\tableofcontents
55

6-
\section style-intro Introduction
6+
\section ssg-style-intro Introduction
77

8-
This page contains a set of guidelines & rules of thumb that we accumulated after 2+ years of using DetectorGraph.
8+
This page contains a set of guidelines & rules of thumb that we accumulated after 3+ years of using DetectorGraph.
99
These are aimed at keeping software design constrained in a way that best takes advantage of the DetectorGraph framework, its expressibility and modeling power.
1010

11-
\section naming-topicstates Naming TopicStates
11+
\section ssg-naming-topicstates Naming TopicStates
1212

1313
Topics carry `TopicStates`. `TopicStates` can express states, events/transitions, operations/requests & responses.
1414
Examples are:
1515
- `FooState`
1616
- `BarSample` when Bar is a sensor.
1717
- `FooBarState`, produced by a `FooBarDetector`. Note that `FooBarDetectorState` is not encouraged as it ties the producer with it's product - but it can be ok in some very specific cases.
1818
- `SomethingRequest` & `SomethingResponse` when implementing a RPC Request/Response pattern.
19-
- `FooBarSettings` for settings that determine how `FooBarDetector` (and by extension `FooBarState`) behave. See also [Settings](@ref settings-topicstate).
19+
- `FooBarSettings` for settings that determine how `FooBarDetector` (and by extension `FooBarState`) behave. See also [Settings](@ref ssg-settings-topicstate).
2020

21-
\section too-big-too-small-tss Too Big & Too Small TopicStates
21+
\section ssg-too-big-too-small-tss Too Big vs. Too Small TopicStates
2222

2323
Hypothetically, the entirety of a system's state could be contained on a single TopicState that is Subscribed to & published to by every detector. Conversely, one could split every individual bit (pardon the pun) of data into separate TopicStates and have detectors only subscribe to the bits necessary to form the data it depends on.
2424
Both are clearly poor separations-of-concern choices and are clear misuses of the DetectorGraph framework - obviously the sweet spot lies in between, but where? Below are a set of guidelines for partitioning Topics:
2525

26-
\subsection type-is-data Type is data
26+
\subsection ssg-type-is-data Type is data
2727

2828
\par "A rose by any other name would smell as sweet" — Juliet
2929

@@ -46,7 +46,7 @@ From [Beat Machine](@ref beatmachine.cpp):
4646

4747
Inheritance can save you some typing and be OK when literally all you're changing is the type 'name' and when you know the data structure will never change and when the 'is a' relationship holds strongly. Inheritance is the lazy approach but that you'll likely have to ditch (at great expense possibly) at some point in the future.
4848

49-
\subsection empty-topics Trivial/Empty Topics are sometimes fine.
49+
\subsection ssg-empty-topics Trivial/Empty Topics are sometimes fine.
5050

5151
Sometimes all a topic needs to express is the fact that _it updated_, that it _happened_ or any other purely unary signals:
5252

@@ -55,7 +55,7 @@ From [Trivial Vending Machine](@ref trivialvendingmachine.cpp):
5555
From [Fancy Vending Machine](@ref fancyvendingmachine.cpp):
5656
@snippet fancyvendingmachine.cpp Trivial TopicState
5757

58-
\subsection atomic-change Variables/bits/data that change together atomically belong together.
58+
\subsection ssg-atomic-change Variables/bits/data that change together atomically belong together.
5959

6060
Examples:
6161

@@ -65,7 +65,7 @@ A product and its new price:
6565
A robot's pose and a timestamp:
6666
@snippet robotlocalization.cpp Mutually Atomic Variables
6767

68-
\subsection mutually-exclusive Mutually exclusive states also belong together.
68+
\subsection ssg-mutually-exclusive Mutually exclusive states also belong together.
6969

7070
@code
7171
struct DoorState : public TopicState
@@ -81,19 +81,19 @@ struct DoorState : public TopicState
8181

8282
This also includes Topics used to drive (or driven by) a finite state machine.
8383

84-
\subsection everything-is-a-service Topics are APIs
84+
\subsection ssg-everything-is-a-service Topics are APIs
8585

8686
Another rule of thumb is to think of Topics as APIs themselves; they should be as general as possible. More general TopicStates tend to better isolate concerns and be more reusable in the future. In general, when creating a topic don't name it with respect to what it'll be used; instead try to name it according to what information it carries.
8787

88-
\section dependencies Detectors and Topics Dependencies
88+
\section ssg-dependencies Detectors and Topics Dependencies
8989

9090
One of the main advantages of using DetectorGraph is a very clear isolation of dependencies & concerns. To maintain those advantages DetectorGraph code should comply with the following rules:
9191
- Detectors should not have any dependencies on any other Detectors: no data-structure dependencies nor runtime/callgraph dependencies.
9292
- Detectors can depend on any number of Topics; ideally only the Topics it Subscribes or Publishes.
9393
- Topics can depend on other Topics for data-structures but should never inherit from other Topics.
9494
- Detectors should do no I/O nor should they talk to other dynamic software modules; debug/text logging is probably the one notable exception. It's totally fine to use a math library or an algorithm-specific library but it's not OK to communicate across threads accessing a singleton outside the DetectorGraph.
9595

96-
\section caching-topicstate Caching/Saving TopicStates is the right solution!
96+
\section ssg-caching-topicstate Caching/Saving TopicStates is the right solution!
9797

9898
Sometimes detectors only need a the information in `TopicStateA` when evaluating `TopicStateB`. It may seem like Subscribing to `TopicStateA` is overkill - but it's not. Remember that `Evaluate(TopicStateA)`s is only called when `TopicStateA` changes and thus there's no runtime penalty on having multiple `Evaluate()`s that are called rarely.
9999

@@ -118,11 +118,11 @@ private:
118118
};
119119
@endcode
120120

121-
Note that most `TopicStates` are small bits of data and thus copying by value should always be efficient. In cases where a `TopicState` contains a lot of data, such that copy-by-value would be a problem, it is the responsibility of that `TopicState`s implementation to implement an appropriate shallow copies scheme. For an example of that see [Sharing Memory across TopicStates](@ref sharing-mem).
121+
Note that most `TopicStates` are small bits of data and thus copying by value should always be efficient. In cases where a `TopicState` contains a lot of data, such that copy-by-value would be a problem, it is the responsibility of that `TopicState`s implementation to implement an appropriate shallow copies scheme. For an example of that see [Sharing Memory across TopicStates](@ref ex-pt-sharing-mem).
122122

123-
\section settings-topicstate Settings are also Topics
123+
\section ssg-settings-topicstate Settings are also Topics
124124

125-
Topics should be used to convey settings as well, and caching them is the way to go (see @ref caching-topicstate)
125+
Topics should be used to convey settings as well, and caching them is the way to go (see @ref ssg-caching-topicstate)
126126
@code
127127
class TooHotDetector : public SubscriberInterface<TooHotThreshold>, public SubscriberInterface<Temperature>, public Publisher<TooHot>
128128
{
@@ -144,7 +144,7 @@ private:
144144
};
145145
@endcode
146146

147-
\section flat-evaluates Flat Evaluates vs. Indirect and/or nested member methods
147+
\section ssg-flat-evaluates Flat Evaluates vs. Indirect and/or nested member methods
148148

149149
\par "Flat is better than nested" — Zen of Python
150150

@@ -196,7 +196,7 @@ class TooHotDetector : public SubscriberInterface<Temperature>, public Publisher
196196

197197
In the first example a reader must follow & comprehend what PublishTooHotIfTooHot does before they can conclude that `TooHotDetector` will always publish 1 (and only one) `TooHot` state per input sample. In the second example that relationship is trivial. The intent is to have direct paths from an `Evaluate()` (or `BeginEvaluation()`, `CompleteEvaluation()`) to `Publish` (or `FuturePublish()`, `PublishOnTimeout()`).
198198

199-
\section concentrators-aggregations Concentrators & Aggregations
199+
\section ssg-concentrators-aggregations Concentrators & Aggregations
200200

201201
In many cases detectors provide an accumulated/aggregated view of a set of TopicStates. The simplest & more readable way we found to do this was based on variations of the pattern below:
202202

@@ -237,25 +237,25 @@ In many cases detectors provide an accumulated/aggregated view of a set of Topic
237237

238238
Note the use of CompleteEvaluation to make the general conditional check regardless what inputs have changed.
239239

240-
\section resuming-state Resuming State
240+
\section ssg-resuming-state Resuming State
241241

242242
The best way we found to resume graph states is to use a specific `TopicState` (`ResumeFromSnapshotTopicState`) that contains a de-serialized version of the latest preserved StateSnapshot. Each detector that needs to resume its state then has a chance of inspecting the entire snapshot to reconstruct its state.
243243

244244
Initially it was thought that state resuming could be done simply be re-publishing the stored `TopicStates` but since most Detectors keep state they'd have to subscribe to their own outputs - in a way that the Resume operation would go in reverse order than the normal topological sort of the graph. That was deemed overly complex & contrived and would greatly increase code complexity.
245245

246246
Instead we opted of giving detectors this _know-all_ single chance to restore their state & re-publish any resumed state `TopicStates` as necessary.
247247

248-
For a full example see [Resuming Counter](@ref resuminggraph.cpp) (@copybrief resuminggraph.cpp)
248+
For a full example see [Resuming Counter](@ref resuminggraph.cpp) ( @copybrief resuminggraph.cpp )
249249

250-
\section explicit-calls-to-evaluate Explicit calls to Evaluate()?
250+
\section ssg-explicit-calls-to-evaluate Explicit calls to Evaluate()?
251251

252252
Detector's `Evaluate()` method calls are central to DetectorGraph applications. They are called by the framework in a very specific and coordinated manner (`BeginEvaluation()->n*Evaluate()->CompleteEvaluation()`).
253253

254254
In some situations it may seem appropriate to explicitly/manually call `Evaluate(X)` from within another method of a Detector to process a specific (e.g. initial) version of X - that's sometimes an *anti-pattern*. When a reader encounters an `Evaluate(Z)` method he/she expects that to only be called when Z has changed - and most of the times that's also what log messages inside `Evaluate(Z)` will have log readers believe. By manually calling `Evaluate()` you break that expectation.
255255

256256
More than once this had led debugging along a completely wrong path and makes `Detector`s program flow less flat and more convoluted. If a single set of operations is necessary for multiple different inputs it is better to implement that as a separate function and have that called from both `Evaluate()`s.
257257

258-
\section initial-states Publishing Initial States
258+
\section ssg-initial-states Publishing Initial States
259259

260260
Detectors do not have a specific mechanism for publishing their initial states/prime outputs.
261261

@@ -267,11 +267,11 @@ Instead the suggested pattern going forward is to always rely on `ResumeFromSnap
267267

268268
In the past we have used a specific `TopicState` (say `DetectorGraphInitialized`) that detectors can subscribe to to be notified when the system boots and publish any new state they may need to. That solution is redundant and not as canonical as the solution described above so it's not recommended anymore.
269269

270-
For a full example see [Resuming Counter](@ref resuminggraph.cpp) (@copybrief resuminggraph.cpp)
270+
For a full example see [Resuming Counter](@ref resuminggraph.cpp) ( @copybrief resuminggraph.cpp )
271271

272-
\section namespaces Usage of Namespaces
272+
\section ssg-namespaces Usage of Namespaces
273273

274-
All DetectorGraph names should be inside the `DetectorGraph` namespace. Within an application it is suggested to have a single namespace reserved for all your Detectors & TopicStates; that allows you to use short names & appropriate names for those without risk of collision. We have also used separate namespaces for TopicsStates & Detectors but that didn't yield much readability or expressibility. Things to keep in mind when making your decision:
274+
All DetectorGraph names are inside the `DetectorGraph` namespace. Within an application it is suggested to have a single namespace reserved for all your Detectors & TopicStates; that allows you to use short names & appropriate names for those without risk of collision. We have also used separate namespaces for TopicsStates & Detectors but that didn't yield much readability or expressibility. Things to keep in mind when making your decision:
275275

276276
- Detectors' names are used not used often in code.
277277
- Detectors have a dependency on Topics.

doxygen/template_bloat.dox

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,9 @@ namespace DetectorGraph
88

99
\section template-intro Introduction
1010

11+
\warning This document is pretty out of date and is likely deprecated in some
12+
ways.
13+
1114
The framework relies extensibly on the use of _C++ Templates_ and that raises
1215
the concern that it might result in
1316
[Code Bloat](https://en.wikipedia.org/wiki/Code_bloat). _C++ Templates_ result
@@ -159,7 +162,7 @@ The below internal classes could potentially be non-template classes:
159162
- [GraphInputDispatcher<T>](@ref GraphInputDispatcher)
160163

161164
Without changing any public API's. One way to achieve that could be to use
162-
`::bind` to link it to the desired `PushData<T>` or `SubscriberInterface<T>::Evaluate`.
165+
`\:\:bind` to link it to the desired `PushData<T>` or `SubscriberInterface<T>\:\:Evaluate`.
163166

164167
\section finally Conclusion
165168

doxygen/topic_inspection_apis.dox

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
/**
22
@page topic_inspection_apis New Topic Inspection APIs
3-
3+
@brief Two new APIs useful within Unit Tests
4+
@par
45
As a part of the effort to enable the `DetectorGraph` `Lite` target we created new APIs for inspecting Topics that make it easier to inspect Topics during Testing (e.g. Unit Testing a Detector) and that work both on `Full` & `Lite` targets. These are:
56
@code
67
bool Topic<T>::HasNewValue() const

0 commit comments

Comments
 (0)