• R/O
  • SSH

コミット

タグ
未設定

よく使われているワード(クリックで追加)

javac++androidlinuxc#windowsobjective-ccocoa誰得qtpythonphprubygameguibathyscaphec計画中(planning stage)翻訳omegatframeworktwitterdomtestvb.netdirectxゲームエンジンbtronarduinopreviewer

コミットメタ情報

リビジョンd2a854f870d7453c8aa575e81013b5fa2405be6a (tree)
日時2020-03-22 01:03:32
作者Albert Mietus < albert AT mietus DOT nl >
コミッターAlbert Mietus < albert AT mietus DOT nl >

ログメッセージ

Pub/Sub: concept done (draft)

変更サマリ

差分

diff -r 9ec6ed103222 -r d2a854f870d7 SoftwareCompetence/DesignWorkShops/PubSub/concept/API.rst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SoftwareCompetence/DesignWorkShops/PubSub/concept/API.rst Sat Mar 21 17:03:32 2020 +0100
@@ -0,0 +1,81 @@
1+.. Copyright (C) 2020: ALbert Mietus.
2+
3+.. _PubSub_API:
4+
5+===============
6+The Pub/Sub API
7+===============
8+
9+As typical with *Design Patterns* there are many ways to implement it. Here we focus on the “Topic” approach. It
10+decouples modules by defining a generic interface, and act as a kind of “man-in-the-middle”.
11+
12+Topic
13+=====
14+
15+.. currentmodule:: pubsub
16+
17+.. class:: Topic
18+
19+ A :class:`~pubsub.Topic` is like a channel to distribute information (events), in a **Pub**/*Sub* environment.
20+
21+ This will decouple the :class:`pubsub.AbstractType.Publisher` from the :class:`pubsub.AbstractType.Subscriber` (in
22+ both directions).
23+
24+ * On one side is a ``Publisher`` that provides ‘data’ (**value**’s, *events*, ...).
25+ * The other side has ``Subscribers`` which subscribe to the topic (with **callbacks**).
26+ * Both ``Publisher`` and ``Subscriber`` are abstract types; there is no contrete class (needed).
27+ * Any module that calls :meth:`publish` is called a ``Publisher``; likewise a ``Subscriber`` is anyone calling
28+ :meth:`subscribe`.
29+ * Commonly there is only one ``Publisher`` (for a given Topic); that is not mandatory however.
30+
31+
32+.. method:: Topic.publish(value, force=False):
33+
34+ This method is called by the ``Publisher``, whenever new **value** is to be shared. When **force** is `False`
35+ (default), the ``value`` wil only be distributed when it differs from the previous value. To force distribution, set
36+ **force** to `True`.
37+
38+.. method:: Topic.subscribe(callback):
39+
40+ This method is called by all ``Subscribers`` to *register* a **callback**, that is called on new ‘data’.
41+
42+ .. _PubSub_callback_signature:
43+
44+ The passed **callback** (any `callable`, like a :func:`~pubsub.AbstractType.callback_function_type`
45+ :meth:`~pubsub.AbstractType.callback_method_type`) will be called when ‘data’ is available. It
46+ has a signature like::
47+
48+ def callback([self,] value, topic):
49+
50+ Where **value** is the ‘data’ passed to :meth:`publish` and **topic** is the :class:`~pubsub.Topic`
51+ instance itself.
52+
53+ When the callback is a method the `self` parameter is automagical remembered by python. For function-callbacks, leave
54+ it out.
55+
56+Supporting types
57+================
58+
59+.. currentmodule:: pubsub.AbstractType
60+
61+Both the ``Publisher`` and the ``Subscribers`` are *Abstract Types*.
62+
63+.. class:: Publisher
64+
65+ Any code that will call :meth:`pubsub.Topic.publish`. It can be a class, a module or just code ...
66+
67+.. class:: Subscriber
68+
69+ Everybody calling :meth:`pubsub.Topic.subscribe`. Typically, the :class:`Subscriber` has a **callback**
70+ function/method too. See :ref:`PubSub_callback_demo` for an example.
71+
72+ Often, it has a method that act als callback.
73+
74+
75+callbacks
76+---------
77+The generic signature for callbacks is simple:
78+
79+.. function:: callback_function_type(value, topic)
80+.. method:: callback_method_type(self, value, topic)
81+
diff -r 9ec6ed103222 -r d2a854f870d7 SoftwareCompetence/DesignWorkShops/PubSub/concept/PubSub-newspaper.puml
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SoftwareCompetence/DesignWorkShops/PubSub/concept/PubSub-newspaper.puml Sat Mar 21 17:03:32 2020 +0100
@@ -0,0 +1,42 @@
1+@startuml
2+hide footbox
3+participant Publisher as P
4+participant You as S1
5+participant "Somebody" as S2
6+participant "Else" as S3
7+
8+== Get your subscription ==
9+
10+P //-- S1 : Subscribe to newspaper
11+...
12+[--\ P : //news//
13+activate P
14+P -> S1 : Get your copy
15+deactivate P
16+
17+== Everybody got its own **copy** of the //same// newspaper ==
18+
19+
20+P //-- S2 : Another subscription
21+P //-- S3 : Another subscription
22+
23+...
24+[--\ P : //news//
25+activate P
26+P -> S1
27+P -> S2
28+P -> S3
29+deactivate P
30+
31+== Until it is canceled ==
32+
33+P //-- S2 : unsubscribe
34+...
35+[--\ P : //news//
36+activate P
37+P -> S1
38+P -> S3
39+deactivate P
40+
41+
42+@enduml
diff -r 9ec6ed103222 -r d2a854f870d7 SoftwareCompetence/DesignWorkShops/PubSub/concept/Use.rst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SoftwareCompetence/DesignWorkShops/PubSub/concept/Use.rst Sat Mar 21 17:03:32 2020 +0100
@@ -0,0 +1,60 @@
1+.. Copyright (C) 2020: ALbert Mietus.
2+
3+.. _PubSub_use:
4+
5+===
6+Use
7+===
8+
9+As typical with *Design Patterns* there are many ways to implement it. Here we focus on the “Topic” approach. It
10+decouples modules by defining a generic interface and act as a kind of “man-in-the-middle”.
11+
12+Both the ``Publisher`` and the ``Subscribers`` share a common :class:`~pubsub.Topic` instance::
13+
14+ from pubsub import Topic
15+ t = Topic("Just a demo")
16+
17+
18+Publishers
19+==========
20+
21+Publishing a value is very simple; assuming ``t`` is a :class:`pubsub.Topic` instance::
22+
23+ t.publish("Hello World")
24+
25+
26+Subscribers
27+===========
28+
29+Each subscriber should register a ``callback``, which will be called “automagical” when a new value is available::
30+
31+ t.subscribe(demo_cb)
32+
33+Where ``t`` is topic (an instance of :class:`pubsub.Topic`) and ``demo_cb`` is the *callback*. This can a function or other
34+kind of callable. Multiple subscriptions are possible, by registering another::
35+
36+ t.subscribe(demo_oo_cb)
37+
38+.. _PubSub_callback_demo:
39+
40+callbacks
41+---------
42+
43+A callback is a callable, that should process the new value. Basically, it is just a function (or method) with the
44+correct signature. A trivial example is::
45+
46+ def demo_cb(value, topic):
47+ print("Function-Demo:: Topic: %s has got the value: %s" %(topic, value))
48+
49+It can also be a method, when you prefer an OO-style::
50+
51+ class Demo:
52+
53+ def demo_oo_cb(self, val, topic):
54+ print("Method-demo: I (%s) got '%s' from topic %s" %(self, val, topic))
55+
56+.. seealso::
57+
58+ * :class:`pubsub.AbstractType.Publisher`
59+ * :class:`pubsub.AbstractType.Subscriber`
60+ * :ref:`CallBack Signature <PubSub_callback_signature>`
diff -r 9ec6ed103222 -r d2a854f870d7 SoftwareCompetence/DesignWorkShops/PubSub/concept/advantages.rst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SoftwareCompetence/DesignWorkShops/PubSub/concept/advantages.rst Sat Mar 21 17:03:32 2020 +0100
@@ -0,0 +1,51 @@
1+.. Copyright (C) 2020: ALbert Mietus.
2+
3+Advantages
4+==========
5+
6+For software-engineers, Pub/Sub has many advantages. The most obvious one is *decoupling*, another one is *scaling*. It
7+is also simple to :ref:`PubSub_use`.
8+
9+And, with Pub/Sub you will automatically use
10+`‘Dependency Inversion’ <https://en.wikipedia.org/wiki/Dependency_inversion_principle>`_, one of the
11+`SOLID <https://en.wikipedia.org/wiki/SOLID>`_ principles; as well as
12+`‘Dependency Injection’ <https://en.wikipedia.org/wiki/Dependency_injection>`_, which often simplifies testing.
13+
14+
15+Coupling
16+--------
17+
18+By and lange, software-routines have to pass information. From one function to another, from one class to another, or
19+from one module to some other module(s). Especially this latter case is annoying, when it is implemented by calling a
20+method of that other module. Then, we speak about **tight** (and *static*) **coupling**: the module effectively can’t
21+perform without the other. When that “other” module is a stable, generic *library*, it is often considered as
22+acceptable. Although it can disturbed your (unit)-testing; by making it slow.
23+
24+But how about two modules, that are under construction?
25+|BR|
26+Then, both are not “stable” (as they might develop) and being depended on unstable modules is bad. You can’t test
27+independently, you may need to revise when the other is updated, etc. Well you know the troubles ...
28+
29+To overcome this, the modules should be *uncoupled* or *lousily coupled*: Both modules are not allowed to call a
30+function/method of the other one. (Which is easy:-). But still pass information; which might seen impossible at first.
31+
32+This is possible, as the modules do not dependent on each other; instead they both depend on the generic
33+:class:`pubsub.Topic`, as we can see on the :ref:`next page<PubSub_use>`
34+
35+
36+Scaling
37+-------
38+
39+Now and then the same data is needed by multiple “consumers”. That number of “users” may even grow in future releases. A
40+sensor-value, by example, that was initially only used in one or two routines, may becomes relevant input to many new,
41+fancy features.
42+
43+Imagene a modules that handles (pushing) the brake. Initially it was only needed to slow down the car. Nowadays it will
44+switch-off the cruise control, also. Perhaps, in the future, that same data might influence the volume of the radio; or is
45+needed to automatically “e-call” 112, when there is an serious road accident. Or ...
46+
47+With Pub/Sub, it is easy to distribute data to more and more modules. Even to modules that aren’t yet imagined when you
48+write that sensor-routine! Your current module only has use :meth:`pubsub.Topic.publish`, and that future module can
49+get that data using :meth:`pubsub.Topic.subscribe`; easy!
50+
51+
diff -r 9ec6ed103222 -r d2a854f870d7 SoftwareCompetence/DesignWorkShops/PubSub/concept/index.rst
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/SoftwareCompetence/DesignWorkShops/PubSub/concept/index.rst Sat Mar 21 17:03:32 2020 +0100
@@ -0,0 +1,25 @@
1+.. Copyright (C) 2020: ALbert Mietus.
2+
3+Introduction
4+============
5+
6+An almost trivial example of PubSub is the daily newspaper:
7+
8+ Once you get an subscription, you automatically get each new publication.
9+
10+Typically, your are not the only one. The *same* ‘newspaper’ is send to all subscribers: everybody got his own
11+*copy*. And, when somebody cancels his subscription all others still het there daily update.
12+|BR|
13+Also notice: your copy is undependent of that the neighbours. And, until you subscribe, the publisher does not know
14+you.
15+
16+In software-engineering we call that **uncoupled** or *loosely coupled*; and that is great.
17+
18+
19+.. uml:: PubSub-newspaper.puml
20+
21+.. toctree::
22+
23+ advantages
24+ Use
25+ API
diff -r 9ec6ed103222 -r d2a854f870d7 SoftwareCompetence/DesignWorkShops/PubSub/index.rst
--- a/SoftwareCompetence/DesignWorkShops/PubSub/index.rst Thu Mar 19 11:04:20 2020 +0100
+++ b/SoftwareCompetence/DesignWorkShops/PubSub/index.rst Sat Mar 21 17:03:32 2020 +0100
@@ -8,12 +8,12 @@
88
99 .. sidebar:: **HighTech** vs *Gooogling*
1010
11- When you search for `Pub/Sub`, you will find over 312M hits! Mostly about cloud-computing, and on how servers exchange
12- messages via a *‘broker’*.
11+ When you search for `Pub/Sub`, you will find over 312M hits! Most are about cloud-computing and on how to exchange messages
12+ between servers via a *‘broker’*.
1313 |BR|
14- Often it is infrastructure engenering based.
14+ Often it is infrastructure engineering based.
1515
16- This workshop isn’t about that. We focus on *Modern, Embedded Software Systems*: How can an (HighTech) Software Engineer use
16+ This workshop isn’t about that. We focus on *Modern, Embedded Software Systems*: How can a (HighTech) Software Engineer use
1717 this pattern to create better software.
1818
1919
@@ -59,4 +59,4 @@
5959
6060 .. seealso::
6161
62- * ...
62+ * https://mybinder.org/v2/gh/AlbertMietus/PyMess.ipython-notebools/master?filepath=%2FSoftwareCompetence%2FDesignWorkShops%2FPubSub%2FPubSub-demo.ipynb
diff -r 9ec6ed103222 -r d2a854f870d7 _std_settings/static/SwBMnl-slides.css
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/_std_settings/static/SwBMnl-slides.css Sat Mar 21 17:03:32 2020 +0100
@@ -0,0 +1,33 @@
1+/* SwBMnl-slides style for Juyiter/IPython "download as slides" ...
2+ The custom.css file should import it as:
3+ @import url("/_static/SwBMnl-slides.css");
4+*/
5+
6+/* Gray slides on gray background with blue border*/
7+.reveal .slide-background { background: #808080;}
8+.reveal div.slides {
9+ background: #c0c0c0;
10+ border: 2px solid #000066;
11+}
12+
13+/* Also gray slides in overview-mode. Highligh the current slide a bit */
14+.reveal.overview .slides section { background: #808080;}
15+.reveal.overview .slides section.present { background: #c0c0c0; border: 2px solid #000066;}
16+
17+/* H1, H2 headers in blue; top aligned. H1 in gray backgroud. In contact with (gray, see bellow side)*/
18+.reveal .slides h1 {
19+ color: #000066; background: #808080;
20+ margin-left: -0.5em; padding-left: 1em;
21+ margin-top: -0.5em; padding-top: 0.5em; padding-bottom: 0.5em;
22+}
23+.reveal .slides h2 {
24+ color: #000066;
25+ margin-top: -0.5em; padding-top: 0.5em;
26+}
27+
28+/* Slighly style the input "sidebar". Make the "Header" text-cell-promt gray; as sidebar, in contact with H1 (see above) */
29+.reveal .prompt.input_prompt { border: 1px solid #808080; }
30+.reveal div.text_cell .prompt.input_prompt { border: 1px solid #808080; background:#808080;}
31+
32+/* code section ...*/
33+.reveal .slides section code {background: #808080; color: #000066;}
diff -r 9ec6ed103222 -r d2a854f870d7 conf.py
--- a/conf.py Thu Mar 19 11:04:20 2020 +0100
+++ b/conf.py Sat Mar 21 17:03:32 2020 +0100
@@ -54,4 +54,3 @@
5454 '**': [ 'recentposts.html', 'tagcloud.html', 'postcardHeader.html'],
5555 }
5656
57-html_static_path.append('_static')