This page gathers my raw ideas as they appear in my brain. Therefore comments on this page is just something like as idea snapshot. It do not reveal anyhing on Ideal Software Architecture, but the way concepts comes into my conscience.
Legend |
The thoughts incorporated in ISA appear with this green box containing the location where this idea is taken into account. |
The thoughts partly incorporated in ISA appear with this blue box containing the location where this idea is taken into account. |
The thoughts rejected from ISA appear with this red box containing the location where this idea is rejected if any. |
The thoughts not actually incorporated in ISA appear with this gray box containing the location where this idea is not taken into account. The purpose of this box is mainly for blog internal management. |
#
Normaly the OS should store the objects in a repository. Classes of the object only have pointer to this object (they are indexes).
#
Thougth : The Reality is the name for the whole set of things we percept (or imagine if we follow C.S Piersce) of the World.
The World exists even if there is no one to perceive it.
The reality is a relation needing a subject (us) and an object (the world) exists.
Mathematics therefore are not the real at contrary of what Max Tegmark affirms. It only is a way to model the reality if and only if you chose the right set of axioms that applies to the object (the part of the world) you are observing.
#
In SOA terms, Editions (printed edition, email, etc) are just services like others with one signature, one per edition ! No more no less. The common trouble is to directy expose a generic service taking as argument a printing model (the real service) and data (the real parameters) of the functionnal service of rendering an meaning full artefact as a given document.
The same can be expressed in OO terms. In `LL`, an edition is a class that is the printing model. Objects are constructed furnishing a view (the data). This object implementing a render operation.
#
Edition, SOA ans use case
Editions like SOA Services are both use cases.
An Edition si an Application use case (at this scope for most of them) like user interface based ones.
A service is a system use case, typically exposed by the business layer. it’s extend application, domain , organization, etc. is an other dimension, an almost external property.
An edition is a particular kind of service producing a printed document.
#
`LL` Dependancy Injection methods
There are several types of dependency injection:
■Constructor injection
■Setter injection
■Interface injection
■Field injection: This one’s new, using annotations on fields, parameters but also on constructors or setters
+ Service Locator Design Pattern
At least controvential see Tony Marsen “Dependency Injection is Evil” => Some DI methods should be rejected from ISA.
ToDo : add in References.
See :
http://www.tonymarston.net/php-mysql/dependency-injection-is-evil.html
https://steveschols.wordpress.com/2012/05/14/dependency-injection-vs-service-locator/
https://steveschols.wordpress.com/2012/06/05/i-was-wrong-constructor-vs-setter-injection/
http://www.petrikainulainen.net/software-development/design/why-i-changed-my-mind-about-field-injection/
In the ISA context the following methods appears the best to select :
– Only use DI when it is really needed : YAGNI principle.
– Constuctor => Finally a best low level way.
– Service locator => Because in ISA, the service locator is a at the heart of the OS, of the network, of some feature similar to oSGI and of the Universe concept. So common problems with that DP can be addressed in a common way.
#
As Uncke Bob state, I agree dependancy invertion sould be done thru polymorphisum. “Injection” by the container could be supported in constructor by requesting a Context. The context is the Use Case Scenario that origines the treatment. This Use Case Scenario is executed in a container. At the top level, the container is the Operating System.
#
`LL`
OO, relationship and scalability.
One of OO major problem comes with direct reference to linked objects. They are often supported thru a pointer to the object for unitary links and thru a pointer to a Collection,Array, etc. object for multiple links.
The relationship concept is not supported in it self. It sould be to supports multiplicity, contraints and lazy loading. Other post had been done on That.
To scale well, the Relationship supports could also have a cursor mode to only load a subset of the objects at a given time. The cursor mecanism should supports 2 levels : objects (around 20) and OIDs (around 100).
#
`LL`
Relationship cursor and large data transfer
The cursor mechanism is also a way to deal with large data transfer between organizations.
Say organization X wants to send a large request R to organization Y.
X can call an operation Oy on a Service Object exposed by Y. This operation Oy takes an argument A. The A object act has the request envelope of R. It has proper fields like the sender name or the R request business identifier. It also contains relationships RS with the effective R objects payload.
The initial Oy operation call with A argument is low in size.
As needed and at is charge capacity, Y then can pull data thru the cursors of the RS Relationships (cursor fields fixed the maximum charge acceptable by X). Cursor also deal with transfer interruptions.
When finished, Y will call an Ox service operation exposed by X to acknowledge the whole R request reception.
#
This approach is similar to the data window of the client/server applications. This approach has proven its efficiency.
#
Difference between Field and Relationship
In ISA and in `LL`, there is a difference between Field and Relationship.
Field are just reference to other objects (memory address or OID).
Relationship is an object that give access to related objects with additive features: constraints check, multiplicity, loading/storing features (lazy, cursor, etc.), link to association class.
This is a major difference with usual language, in particular OO ones, and even with the way UML is supported by modeling tools.
This is a way to overtake the unitary essence of OO, in particular to fill the gap with the relational paradigm.
#
In ISA and in `LL`, There is a différence between Field and Relationship.
Field are Just Reference to other Objects (memory adress or OID).
Relationship is an Object That give Access to related objects with additive features: Contraints check, multiplicity, loading/storing features (lazy, cursor, etc), link to association class.
This Is a major diffence with usual langage, in particular OO ones, and even with the way UML is supported by modeling tools.
This Is a way to overtake the unitary essence of OO, in particular to fill the gap with the relationnal paradigm.
—————–
Field: Static (explicity multiplicity: 0..1, 2..4)
Relartionship: Dynamic (open multiplicity: 1..*) (association class).
#
`LL` (mine Last Language) and the “Uncle Bob” ones at The Last Programing Language (Clean Coders)
First mine was named independently of Robert Martin video.
“Uncle Bob” list the last language characteristics and I will quickly give a short statement about each of them:
1/ Cobol and English
[RM] Cobol is a bad language because it try to express programming has natural English language.
[LL] OK a programming language cannot be natural language because of its formal nature, but the closer the natural language, the more readable and writable it is.
2/ Have a paradigm
[RM] We needs a paradigm that restrict the way of doing thinks. Hybrid languages are not consistent.
[LL] OK, of course but not only for the language, for the whole architecture.
3/ Simplicity of syntax.
[RM] Simple syntax to focus on semantic issues instead of syntax issues.
[LL] OK, No keyword in LL just punctuation. Usual languages expressions in base framework (library, O.S. Primitives) => English, Math’s, SQL, RegEx, DSLs.
4/ Polymorphism
[RM] We need polymorphism of OO allows inversion of control flow (dependency inversion) to assemble our modules. The counter part is to avoid function pointer in order to impose this way of making dependencies.
[LL] Fully agree. I also want to avoid static inheritance rigidity.
5/ Virtual machine
[RM] We want to run on a VM to be able to run anywhere and be freed from hardware constraints.
[LL] Strongly disagree. The hardware power increase is consumed by this kind of VM. It is unacceptable to have so slow software on so powerful machines. The source language is portable! If there is only one Last Language a unique native compiler have to be built for each platforms.
6/ Compatibility with existing platform
[RM] The language could be able to call and be called by and from major platforms.
[LL] No. If it is the Last Language with all its nice features (like Universe) it is definitely incompatible with existing platforms. What you could just do is to encapsulate existing systems and interact with them thru services expressed in LL.
7/ Structured programming
[RM] Don’t have a goto and break/continue.
[LL] OK.
8/ Garbage collected
[RM] To avoid memory leaks.
[LL] No because it is inefficient and unpredictable. The smart pointers area far better alternative to automatic memory freeing. More generally, explicit resource freeing often cannot be avoided (connections for instance) and destructor is certainly one of the best place to do so.
9/ Fast
[LL] No I prefer a slow one ;-D
10/ Symbolic
[RM] Not too close from the hardware to be abstract. Avoid thinks like primitive as int.
[LL] I agree about the abstraction, but it this often contradictory with 9/. What we prefer is that common abstractions should be implemented natively in hardware as primitive type. If it is the Last language, the µP founders should do that!
11/ Textual
[RM] Experiences have proven that textual languages are the best ones, certainly because of procedural way of thinking.
[LL] Yes at the programming level. But to design an API, a Database, an object model a graphical language like UML is also necessary. LL should allow all those facets of the software.
Mappings, are often better expressed thru a table or a graphical notation (Cf. Flow language map of Web Methods).
12/ Runtime changes
[RM] Being able to manipulate the code while running. The code is the data and the data is the code.
[LL] Certainly powerful, but quite difficult to imagine. Is it not a way to break software structuration (make a goto in other words) ?
I prefer the more manageable language dynamicity and the capability to execute source code a runtime like RegEx does.
#
`LL`
Syntax and features
For each:
– Semantic: Each element taken in sequence.
– Usage: There is at least one border effect at each loop.
– Runtime behavior: Executed in the thread of the caller object.
– Parameters: Type and name of elements, collection, bloc of code.
For all:
– Semantic: All elements taken all together.
– Usage: There is no border effect in the loop.
– Runtime behavior: Executed in the thread of the called object.
– Parameters: Type and name of elements, collection, bloc of code.
Developed syntax with naming (this syntax allows to avoid ambiguity):
For all: collection: cars, element: type: car, name: “current car”; do:
Current car reevaluate: rate: 0.95.
If: condition: current car value > threshold, then:
Notify: vendors: current car vendors.
.
.
Syntax with type association and 1 loop instruction:
For all: cars, car, “current car”, Current car reevaluate: 0.95.
Syntax with type association and N loop instructions:
For all: cars, car, “current car”,
Current car reevaluate: 0.95.
If: current car value > threshold,
Notify: current car vendors.
.
.
: => Open a list of parameter
. => Close instruction.
Tab => Significant for bloc structuration.
, => Separator of elements in current opened list of parameters.
; => Close the current opened list of parameters.
Parameters mapping inference follow this precedence :
– Type.
– Optionnality.
– Order.
– Naming.
#
Points at the end of a block of code are optionnal if indentation (tabs) are well done.
#
End of line are also significant for object creation and to interpret tabulations.
#
Classes dependancies on other classes (Java import / C# using) are managed at the component level.
A component is a versionned delivery unit (group the concepts of Java package / JAR – .NET namespace / assembly).
A component has version and revision numbers. A component can depends on another component of a given list of versions.
#
Infinite loop
See how to avoid notification reentrance and infinite loop in particular in a distributed environnement.
Transactions identifier is not usable because it can be changed.
#
Infinite loop in distributed environment
The mean to avoid Infinite loop in distributed environment could be to have an internal transaction identifier allocated by the transaction manager associated to the top level use case. The transaction identifier is transmitted by the O.S. With every remote call. If on a given execution node the O.S. Sees that the same object method is called with the same internal transaction identifier, then there is a recursive distributed condition and an exception is thrown. The universe manager is also notified of this.
This mechanism could also detect worm diffusion when recoming on the same node. This limit the worm diffusion to one instance per node, and therefore the possibility to overload the entire universe.
#
N-ary relations are not represented in UML. Because one of the in relation class or an association class can play this role.
This make the concept completly disappering.
I thing it a pity because some interresting semantic is lost, at least for human readybility.
#
If you apply OO to hardware, you can imagine a machine that implements Objects in a ship. This machine would work in a quite different way the Turing machine does.
Say 1 Object is in 1 ship having N registers of 64 bits. These registers are for storing usual registers like ordinal counter, state, A and B accumulators, indirect index, etc. They also store the fields of the object (values or pointers). They also point to the adresses of the classes it implements.
When an object is solicited, it request then acquire an ALU and connect its registers to proceed its instructions for a given quota of usage. Almost no context change is needed (stack push/pull) on ALU allocation.
In this case, an equivalent ship of 1GB of RAM could support near 2 millions objects for 16 registers per object ship.
A more radical option could be to incorporate an ALU in each object ship (but this will waste many electronic component usage). In this case, an equivalent ship of 1GB of RAM could support about 40 000 objects.
Caution: This architecture only make sence if all the calls are asynchronous.
#
OID and scalability thru partitionning
OIDs should have several scheme. OID schemes specify the way they are produced.
The scheme generation field could be : Random, Sequence, Custom or Manual (?).
The scheme partition field specifies that the X left most bits of the OID are reserved for partitionning (by default X is 16 bits). It also specifies the procedure to build of the partition key. It expressed by `LL` code producing an integer value. The Custom sheme is also expressed in this way.
#
`LL`
What is a Property?
Something proper to the object, that is public and that is a data by nature.
A property is part of the interface.
It as the following properties:
– name.
– direction : Read, Write are Read and write.
– mapping : Thru the name of Field, Relationship or method for computed fields (the age of a person for instance).
An operation is something similar to a property but that is a treatment by nature.
It as the following properties:
– name.
– mapping : Method name.
An interface has properties and operations.
#
Persistence, dirty marker and indexes
A way to signal the modified fields, is to have a 64 bits status internal field for Persitent object. One bit per effective field.
The OS could therefore chose to :
– update the fields and the indexes if any on these fields
– write the whole object and update all the indexes
– write the whole object, only update the indexes if any on these fields, and put a redirection at the previous object location to the new one. In this case these redirections can be elimited in background.
#
The base type of an object is its Nature. Its essence that it is all long of its life.
The name Nature is used in `LL` to distingish this type.
OID are generated relativly to this Nature.
#
To avoid things like batch, it could be possible to ask the O.S. to create an object periodicaly. Or more generaly on a time based rule valid on a specified period.
#
`LL`
Consider having a Scripting language on top of LL (a kind of DSL) for easy access (like python or PowerShell), business rules expression, etc.
#
`LL`
Complexity
You cannot avoid complexity because things are what they are.
State machine for instance with all its properties.
Tools come into play to address complexity. Auto layouted diagrams, property editing assistant, auto completion are exemple of that.
#
1 “thread” per object
Have a look to https://en.wikipedia.org/wiki/Transistor_count to see how much simple ALU with few needed registers could put an a regular concentration CPU chip.
#
`LL`
Undo/Redo (Memento Design Pattern)
Since object have an identity and a state, they can be undoable and redoable.
This feature have to be supported as an usual one.
The undo store could be delegated to OS for optimisation and memory managment.
#
`LL`
read only smart pointer
Consider having smart pointers that enforce read only on the object it references (such as Porperty in the sence of the state axiom post).
This could prevent encapsulation violation like those explained below
From https://msdn.microsoft.com/fr-fr/library/ms229006(v=vs.100).aspx
This feature would greatly ensure security and correctness of programs.
#
`LL`
Relationship and field
-> is part of the state of the object and what is not?
Make a field or a Relationship an Attribute , result that any change to it notify a state change to the container object and consequently change its state.
Make a field or a Relationship an Property , result that any change to it notify a state change to the container object and that this change is vetoed.
Not doing that violate the encapsulation principle, as does most languages.
#
Consider having read option in operation arguments, like the const of C++
#
Relationship and state
Source Object : S / Target Object : T
Sample context : A car from its owner point of view. S is the car.
– Simple association object : S ➝ T
When T state changes, S state is not affected.
Life cycles of S and T are independent.
T is parking.
– Aggregate association object : S ◇➝ T
When T state changes, S state is affected.
Life cycles of S and T are independent.
T is wheel.
– Composition association object : S ◆➝ T
When T state changes, S state is affected.
Life cycle of T is linked to the one of S.
T is door.
#
Question to answer about Documents:
What is a Document ?
How objects are incorpored ?
How to manage version (major, minor, build) ?
How to manage inheritance between documents (a document B inherit of the document A but adding/modifying/deleting parts that are referenced by anchors in A => Modifications in A could affect all inheriting documents) ?
How to use and manage layers ?
#
Nodes
Execution nodes are either physical or logical.
A node has a set of resources of 2 different natures : hardware and software.
Hardware : CPUs, RAM, Storages, Network, Diplays unit, Keyboard, etc. each associated with a quantity number.
Software : A universe it belong to, An instance of the Operating System, Object that resides on this Node and a those that are instantiated.
So physical nodes are real hardware machines, while logical nodes are similar to what we named virtual machine (VM).
Physical nodes are always members of the real world universe.
#
O.S. display
An O.S. has mainly two faces : What it can do and What it is doing.
This correspond to the objects that resides on this Node and a those that are instantiated. More precisely, the Objects of category that are of the class Use Case.
In fact, these faces evoluate in time.
Therefore the O.S. is a support for a 3 dimensions space :
– Runnable : What it can do
– Run : What it do
– Time : Past, present and future.
The display of the O.S. should offer a means to evaluate in this space. The focus must be put on the present of Runnable and Running use case objects.
#
Use case and common behaviors
UML use case deal badly with shared behaviors like common features (“Générer écriture comptable”, “Contrôles bloquants”, “Identification SNGI”). They are often modelized thru a use case and linked to the effective use case via an “include” : that’s bad.
There is another kind of shared behavior badly suited : Rules (either business or technical).
Possible solution : Have a shared behavior metaobject that can “apply to” or be “used” by use case. For external systems, they can “include” service use case exposed by that systems.
#
`LL`
Here the inheritance link between use case make sense because common rules can be applied to all childs.
This is a way to “inject” some behavior in the invariant section.
#
`LL`
Exception
Exception is a good feature because it is a structured language construction for dealing in a common way with abnormal situations. However exceptions are often very verbose that is heavy in functional code. So, having a regular method construction could be an interesting compromise.
A method as one exception section and one finally section. It also has an exception attribute with the following values : escalade to caller (default), local management (goes to the exception section), go to context handler (goes to the use case exception handler).
Exception class is typically not involved in a class hierarchy. A management thru error code is much simpler. Error code is either system or use case.
#
`LL`
Overloading
The OOSC book at page 95 about syntactic overloading limitations, and give a preview of semantic overloading, a way to get that problem solved in LL could be the argument inference algorithm taking the type, the name, the position, etc. as the way to determine the appropriate operation to select.
#
Genericity
The OOSC Book at page 97 states that genericity solve one main problem of reusability:type variation.
That’s true, but polymorphism also does that. The type just have to conform to a given more abstract type (interface). The initials implementation of Vector Class or of Comparable interface in Java gives an example of that. Together with type inference and automatic casting this gives a much simpler alternative to type variations.
The only advantage of generics remaining is type checking at compile time.
Does that avoid test need ? Certainly not so compile time checking is more a developer concerns that a robustness one. Easiness to not have generics appears more profitable that the subtle complications they introduce.
#
Distribution is also a solution to tolerate failure and even accidents.
Thru a redondant approach the probability of a disaster affecting all nodes is very very low. This is the approach of the internet protocol and the one of aeronautics systems.
The distribution is also a way to address scalability.
When managed automaticaly, distribution freed from the need of expert in technical architecture and exploitation manual tuning.
#
A distinction has to be done between Object and its representation.
Object Representation is the projection of the Object artefact in the physical real world.
Object Representation applies to Object has they are “in memory”, “on the wire”, “on the disk”.
Object Representation is not an Object, in this sence they are not in the scope of OO. They are over of the OO limits.
Exemple on wire representation:
format:text minified.
encoding: UTF8.
Identifier:6876868858.
Version:23.
length:6758.
content:lsjfm jzefjjfqflqfljefjqelqlwnvln
q lqnz
zflkfh….
#
Windows 10 is updatading on my main desktop, since more than 2 hours !
But what is it doing ? Download was done before, unzipping is not so inefficient, so what ?
Is it because a C, C++ install that takes 15mn on an old machine takes 10 times more with those marvelous virtual machines (like CLR or JVM) on a 2 years old machine with 6Gb of memory and 2 or 4 cores ? (150mn that’s 2 hours and half yes it match)
I am definitly against those kind of VM. And I don’t see any other explaination for a treatment that last more that 2 hours, what can it do that last so long to install a O.S. ????
#
`LL`
Have a semantic id on elements
Each element of a class could have a global semantic id: Class, Attributes, Properties, Operations. This id is attributed by some central authority like wikipedia.
This id allows to multilingualy make inference on objects.
The authorities or others can have a semantic graph of terms ids to increase the meaning capabilities.
For example, with this kind of ids, translation can be done automaticaly in a very accurate manner.
#
Here emerge the question of the kind of id.
OID is of course the only possible choice. This makes the semantic to point to an object.
Does that influence the OID format?
The OID could be structured or not.
If it is not, to know the semantic a request to at least one general purpose center have to be done, with the risk af an unknown reference. If known by the general purpose center a single request could be enough, but the number of request is not predictable, even in the worse case the answer cannot be found.
If it is, the originator class can be known, deducted or determined via a request, then a request to that originator gives the answer.
Here the maximum request number is 2, with a warranted resolution.
#
It is better not to have to choose between strutured vs non-strutured OID format (being both static and dynamic).
So it is possible to reserve the left most bit of the class id part of OID for selecting strutured or non-strutured. If 0 the remaining 63 bits are a hash code of the class full name. If 1 they are a random number.
The same policy could apply to the object id part of an OID. Here when 0 the remaining 63 bits are a sequence number (with possibliy right most bits for the node number).
This policy avoid generation rule collision between a static algorithm and a random generator.
Both hash code and random operations could be implemented in silico.
#
This segregation in object id part is important for objects that could be created both on central nodes and on ditributed ones in particular in the case of disconnected situations. This avoid the need to consolidate OIDs when pushed to central nodes. Consolidation are complicated and even impossible in some case when OIDs are propagated externally, consolidation are bottleneck in particular if implemeted thru an alias mecanism (2 OID for 1 object).
#
Post-condition and Class invariant
To be fully supported, these feature must be associated with a transactional mechanism ensuring object consistency.
Eiffel software almost recommend to only turn on these features at development and test time. This is certainly because transaction management is very costly, in particular the capability to rollback.
#
Class Arithmetic
A: a, z.
B: b, z.
C: B + c,d. = B UNION c, d. = B ∪ c, d.
C inherits of B. C is a B.
C ∣ b, z (B); c, d.
D: A + B.
D inherits of A and B. D is a A and a B.
D ∣ a, z(A), b, z(B).
E: A INTERSECTION B. = A ∩ B.
E reify the commons of A and B. It fusion the shared members. E is more general that A and B.
E ∣ z.
F: A – B.
F has the members of A exempt those of A ∩ B.
F ∣ a.
Examples:
Date: day, month, year.
Time: hour, minute, second.
Date time: Date + Time.
Apple: colors, juice.
Pear: colors.
Fruit: Apple ∩ Pear.
Shape: surface.
Circle: Shape + radius.
Rectangle: Shape + length, width.
Square: Rectangle + side, invariants: side=length, side=width.
Here the Square class is incorrect because it does not in anycase be a substitute of a a Rectangle. This is clearly shown be the invariants thats add a constraint on Rectangle fields. The Liskov substitution principle is broken.
This illustrate that the this arthmetic differs from the maths one
Typically, Class Arithmetic applies to classes objects and the left value is always a new class.
It could not apply reflexively to a class elsewhere all objects belonging to that class have to be updated. This is only imaginable in a software evolution process (with versioning). Therefore in a new version of the class, so another class.
#
Object Arithmetic
Object Arithmetic is similar to Class Arithmetic except that it also applies to object and to their instances.
In fact, typicaly this arithmetic is reflexive as we can see below:
the a: the a +
new B: b:the b value, z: the z value.
.
This applies addition of B class object to the a object. When validated, it also applies all the instance of the a object.
#
View update and time to live
Views are typically updated asynchronously. As previously stated, is is prefered to the Object to retain its observers and to delegate the update to the network.
So what to do if the network cannot notify the view. Here is an algorithm for that situation:
1. Object O send a view version Vj to the distributed infrastructure in destination to X views giving a retry interval RI and a peremption date time PD
2. If the is view V is reachable it is updated if Vj > Vi (where Vi is the current version of the view V).
Normal end.
3. If the view V is not reachable, the distributed infrastructure does the following:
3-1. If the PD date is overdated, notify O that Vj cannot be send to V. O answer either by a new PD or tell to the distributed infrastructure to discard the notification and it removes V from X. In this last case, the view V is considered definitely lost. If it ressusite it has to reestablish its subcribing, it know that by detecting that its PD is overdated.
Lost end.
3-2. If PD is not overdated, wait for RI and then loop to 2.
#
O.S. command line is an `LL` interpreter
Commands are use case.
The sequence is:
1
Invoque the construtor be its name followed by arguments. The firt one is the scenaario, if omited the main one.
2
Run the constructor to initialuze the UC.
3
At its ends, a hook is positionned by the base UC class that do the rest of the job.
4
Run preconditions.
Launch the scenario
The base UC constructor provides some general purpose argument: Scenario, wait/no wait, display, demon and things like that.
#
`LL` at OS command line
Hello World sample
>Hello World
Hello every body
>
Here the Hello World use case class is solicited, the main scenario is invoked.
>Hello World with name Luc
Hello Luc and every body
>
Here the Hello World use case class is also solicited, the scenario “with name” is invoked.
The argument inference is very important for a fluent language.
#
Having a fluent language is very important for usablility.
Cobol is certainly the most successful language. The fact that its base paradigm is to be the nearest of english as possible is certainly not stranger to that. So I disagree Uncle Bob, that a language should not be close of a natural language. OK, not too close, but the closest as reasonable.
#
Use Case (UC) and OO
UC promotes functionnal decomposition in a temporal way that is not compatible with the OO, B. Meyer in OOSC (pages 105 to 112 and 738) explains that very well. It also only has an external point of view.
On the other hand, UC are a convenient, efficient, precise and very diffused way of expressing software external specification. While OO direct approach is not easy at all for that job.
In other words, UC are right to express the problem and OO is right for the solution, but UC and OO are orthogonals.
=> ISA have to find a way to fill the gap between that two approaches.
I propose the notion of Domain (supported by `LL`).
– A UC is a feature made available to a user (a role). With that primar definition, UC are not linked to a method (UML, UP, Argile, etc.). It describe a temporal sequence of interactions thru scenarios.
– A Domain group together cohesive UC. It is the place where these UC shared parts are expressed. The involved objects (up views). The shared behaviors, like business rules. It is also a place to put requirements, functionnal or non functionnal.
– In the same way, a BPM is a macro-feature. It involve several user roles of one or more Domains. They orchestrate UCs.
– The Domains is much closer of the OO approach that UC, and they appears not to be difficult to express by analysts (it fact this kind of global view also miss to them). UC are rid of the background informations and can concentrate on orchestration.
The Domain hierarchy is a way to express what is the system, its essence, without functional temporarily.
Model:
Domain ◆─0..1───0..*─ Use Case
Domain ◆─0..1───0..*─ Domain
BPM ◇─0..*───2..*─ Use Case
Use Case ◆─1───1..*─ Scenario
Scenario is the only behavioral element supported in UC in order to limit feature implemented in a UC because the core must be delegated to Objects.
Scenario ◆─1───1..* {orchestred}─ Call of Behavior
Behavior are expressed thru Operation or State Machine, or even Use Case Scenario for called Use Case by another Use Case.
Domain ◆─0..1───0..*─ Up View
Up View corresponds to the usual Business Object concept. They have fields and theirs life cycle are expressed thru state machine.
Domain ◆─0..1───0..*─ Behavior
Domain ◆─0..1───0..*─ Requirements
Requirements ──1..*──┬──1..*─ Use Case
Test Point
Test Point ◆─1────1..*─ Test Case
#
Use case are also useful for 2 reasons:
– you don’t build a system in the absolute but in order to serve a set of functionalities, so you can’t avoid to take that into account in design. Use cases provide that.
– use cases specifies the external interface of your system, and in particular the entry points. Anyway, you need that to be expressed in any manner.
#
Overload is bad
It introduce an heavy syntax and destroy the class namespace.
So having optional arguments is a much more elegant and powerful (thing about explicit default values) feature.
The class namespace is consistant and the member name is sufficient to point one and only one. This is useful in particular for diagrams for instance.
#
In fact it is not much then client / supplier model that is efficient, it is the notion of contract.
A provider giving you rotten oranges it is completely possible so you have just your eyes to cry.
What warranties that the oranges are nice or ad exception is thrown it is the contract. In the real life this contract is more or less formal.
#
In `LL` no escape characters should exist.
All characters are what they are.
The compiler should makes it’s best effort to deducte the code words from the literal one.
Another possibility is to declare literals dedicated section.
A possibile policy could be following:
1/ A single line per instruction. Then a line always finish by a . followed by an end of line.
2/ If a literal do not have end of line nor represents code portion: write it directly or define a literal field in the class.
3/ Else, define a new literal or code object than only contains one and only one literal or code expression. Reference this object by its OID or a name.
The type model could define a Litteral type that is like a String except that is is immutable. A Litteral could defined and used a Design time and at Runtime.
#
`LL` Sample code of the use case object:
Scenarios:
Main:
User interface console display line Hello world..
.
.
Where user interface is a use case field, console a property of this object and display line an operation of the console. The printed message is “Hello world.”.
The compiler proceed as followed:
A list of scenarios have to be proceeded, then a first scenario is initiated, it’s name is main. The main scenario is followed by a sequence of instructions. Then the first instruction is proceeded. The user word is not recognized, it is just a text at the moment. The word interface is grouped with the previous text, here user, to forms the user interface group, this group is recognized in the space of names as a field of the current object, the use case: this word group is recognized. Etc.
– Or
Literals:
Hello: Hello world!
.
Scenarios:
Main:
User interface console display line Hello.
.
.
– Or with a literal object that always finishes in the same way:
Object: name: hello message, class: literal.
Text: the message
On several lines.
With . Dot
.
.
Scenarios:
Main:
Variable message: OS get object by name hello message.
User interface console display message.
.
.
Here 2 compiler considerations must be explained for this syntax to work.
First the use of type inference for the Variable message.
Second, any `LL` line have just one instruction. This both allow this syntax and promote programs text simplicity and explicity. The compiler could after that easily optimize the code in removing the Variable message.
The only exception to this rule is for literal expression in a dedicated object or in tables.
– Or with a literals object having a table of messages with a name and a text message.
#
`LL`
OID format:
Class ID,Organization ID,Object ID,Version ID.
All ID are 64 bits.
– Class ID: The hash code of the full qualified name. This part is optionnal if the class is not ambigous.
– Organization ID: The hash code of the organization name. This part is optionnal in a given Universe.
– Object ID: The core object ID. This part is mandatory.
– Version ID: The object version. Only needed for concurrent persistence context or when historization is required.
The Object ID could optionnaly have 2 parts to avoid collision in wide separated emitters : 1 part for the site and 1 part for a generated (sequence or random)
#
Allocating UP TO 50% of a phycisal ressource staticaly and the remaining percents to dynamic allocation could not be limited to bandwith ressource but all ones (CPU, memory, storage access, etc.).
This is the only way to absolutly ensure an execution time at a task.
#
Putting Use Case at the O.S level also solve in somme way the SOA Service dilemna about granularity.
Often there is macro-service (Web Service) that expose the whole API of a system. It could be better to have a more fine grained level.
The Use Case at the O.S. level push at the heart of the computing its characteristics : Goal, Pre-conditions, Post-condition, Scenarios, etc.
This promote and even solve the granularity problem.
#
A service is a kind of use case. A use case used (typically) by a computing system.
The notion of command (console or shell), is absolutly similar except that is it (typically) used localy and its goal is about computing purpose: that’s all. So a command is also a service that are all the same kind of use case.
The shell is just a way to launch them. It is in fact a `LL` interpreter. PowerShell is the nearest exemple of that kind of interpreter console.
#
Apart of the abose use case kind distinction, use case can also be discriminated in the one that can be run directly, at the O.S. level. And the one that only make sence in the context of a more global use case. For instance, changing the style of a paragraph, that is a use case, only make sence in the context of a more general use case that allow document editing.
So it could be possible to distinghish “top level use case” from “dependant use case”.
NB: See if that is good in the way of the problem reveled by B. Meyer problems of functionnal decomposition.
#
This thought is in contradiction with another one to prevent hierarchical functionnal decomposition.