I have struct chartManager which contains struct of series and struct series which contain struct of points. and they are all in Chart class.
something like this
Class Chart
{
protected:
struct points
{
int seriesPoints[10];
};
struct series
{
points seriespoints;
char seriesName[20];
};
struct pageManager
{
char chartName[20];
series totalSeries[5];
};
};
How do i show this in class diagram??
A good answer is : never go from specific language to UML :)
Nevertheless, composition/aggregation with cardinality is for me the way to go (a struct is pretty the same as a class).
I see this is a old post, but maybe I can help someone with my answer.
The best way to describe the above example is with "Nesting" connections.
Composition or Aggregation prerequisite that they are independent and not within the class itself.
Related
Recently I started to learn Rust and one of my main struggles is converting years of Object Oriented thinking into procedural code.
I'm trying to parse a XML that have tags that are processed by an specific handler that can deal with the data it gets from the children.
Further more I have some field members that are common between them and I would prefer not to have to write the same fields to all the handlers.
I tried my hand on it and my code came out like this:
use roxmltree::Node; // roxmltree = "0.14.0"
fn get_data_from(node: &Node) -> String {
let tag_name = get_node_name(node);
let tag_handler: dyn XMLTagHandler = match tag_name {
"name" => NameHandler::new(),
"phone" => PhoneHandler::new(),
_ => DefaultHandler::new()
}
if tag_handler.is_recursive() {
for child in node.children() {
let child_value = get_data_from(&child);
// do something with child value
}
}
let value: String = tag_handler.value()
value
}
// consider that handlers are on my project and can be adapted to my needs, and that XMLTagHandler is the trait that they share in common.
My main issues with this are:
This feels like a Object oriented approach to it;
is_recursive needs to be reimplemented to each struct because they traits cannot have field members, and I will have to add more fields later, which means more boilerplate for each new field;
I could use one type for a Handler and pass to it a function pointer, but this approach seems dirty. e.g.:=> Handler::new(my_other_params, phone_handler_func)
This feels like a Object oriented approach to it
Actually, I don't think so. This code is in clear violation of the Tell-Don't-Ask principle, which falls out from the central idea of object-oriented programming: the encapsulation of data and related behavior into objects. The objects (NameHandler, PhoneHandler, etc.) don't have enough knowledge about what they are to do things on their own, so get_data_from has to query them for information and decide what to do, rather than simply sending a message and letting the object figure out how to deal with it.
So let's start by moving the knowledge about what to do with each kind of tag into the handler itself:
trait XmlTagHandler {
fn foreach_child<F: FnMut(&Node)>(&self, node: &Node, callback: F);
}
impl XmlTagHandler for NameHandler {
fn foreach_child<F: FnMut(&Node)>(&self, _node: &Node, _callback: F) {
// "name" is not a recursive tag, so do nothing
}
}
impl XmlTagHandler for DefaultHandler {
fn foreach_child<F: FnMut(&Node)>(&self, node: &Node, callback: F) {
// all other tags may be recursive
for child in node.children() {
callback(child);
}
}
}
This way you call foreach_child on every kind of Handler, and let the handler itself decide whether the right action is to recurse or not. After all, that's why they have different types -- right?
To get rid of the dyn part, which is unnecessary, let's write a little generic helper function that uses XmlTagHandler to handle one specific kind of tag, and modify get_data_from so it just dispatches to the correct parameterized version of it. (I'll suppose that XmlTagHandler also has a new function so that you can create one generically.)
fn handle_tag<H: XmlTagHandler>(node: &Node) -> String {
let handler = H::new();
handler.foreach_child(node, |child| {
// do something with child value
});
handler.value()
}
fn get_data_from(node: &Node) -> String {
let tag_name = get_node_name(node);
match tag_name {
"name" => handle_tag::<NameHandler>(node),
"phone" => handle_tag::<PhoneHandler>(node),
_ => handle_tag::<DefaultHandler>(node),
}
}
If you don't like handle_tag::<SomeHandler>(node), also consider making handle_tag a provided method of XmlTagHandler, so you can instead write SomeHandler::handle(node).
Note that I have not really changed any of the data structures. Your presumption of an XmlTagHandler trait and various Handler implementors is a pretty normal way to organize code. However, in this case, it doesn't offer any real improvement over just writing three separate functions:
fn get_data_from(node: &Node) -> String {
let tag_name = get_node_name(node);
match tag_name {
"name" => get_name_from(node),
"phone" => get_phone_from(node),
_ => get_other_from(node),
}
}
In some languages, such as Java, all code has to be part of some class – so you can find yourself writing classes that don't exist for any other reason than to group related things together. In Rust you don't need to do this, so make sure that any added complication such as XmlTagHandler is actually pulling its weight.
is_recursive needs to be reimplemented to each struct because they traits cannot have field members, and I will have to add more fields later, which means more boilerplate for each new field
Without more information about the fields, it's impossible to really understand what problem you're facing here; however, in general, if there is a family of structs that have some data in common, you may want to make a generic struct instead of a trait. See the answers to How to reuse codes for Binary Search Tree, Red-Black Tree, and AVL Tree? for more suggestions.
I could use one type for a Handler and pass to it a function pointer, but this approach seems dirty
Elegance is sometimes a useful thing, but it is subjective. I would recommend closures rather than function pointers, but this suggestion doesn't seem "dirty" to me. Making closures and putting them in data structures is a very normal way to write Rust code. If you can elaborate on what you don't like about it, perhaps someone could point out ways to improve it.
I have started out learning Rust and is currently trying to write a small neural network as personal exercise. I want to define a struct for my forthcoming Layers/Clusters/Groups of nodes. My initial definition looks like this:
struct Layer {
name: String, // Human readable name
id: String, // UUID in the future
order: u8, // int for sorting
width: u8, // Number of nodes
input: [&'Self], // References to other Layers that feed input into this
}
The thing I am struggling with is the input field which should contain a list of references to other Layer-instances. I will know at compile time how many each Layer will have in the list so it wont have to me mutable. Is it possible to do this? I cant find a solution on the Google machine or in "the book".
Please advise.
Is it possible to do this? I cant find a solution on the Google machine or in "the book".
Possible yes, though I would not recommend it.
Let's start with the possible: &Self would be a "layer reference" with an unnamed lifetime, a lifetime name is for the form '<symbol>, so when you write &'Self you're specifying a reference of lifetime 'Self, but you're never specifying the type being refered to, which is why rustc complains about "expected type".
If you add a "proper" lifetime name, and parametrize the structure, it compiles fine:
struct Layer<'sublayers> {
name: String, // Human readable name
id: String, // UUID in the future
order: u8, // int for sorting
width: u8, // Number of nodes
input: [&'sublayers Self], // References to other Layers that feed input into this
}
However I would not recommend it as the last member being a slice means it's a DST which are difficult to work with at the best of time -- as the nomicon specifically notes "custom DSTs are a largely half-baked feature for now".
Since Rust doesn't yet have const generics proper you can't use an array you'd parameterize through layer either (e.g. Layer<const Size> and input: [&Self;Size], maybe one day), so you probably want something like a vector or a slice reference e.g.
struct Layer<'slice, 'sublayers: 'slice> {
name: String, // Human readable name
id: String, // UUID in the future
order: u8, // int for sorting
width: u8, // Number of nodes
input: &'slice [&'sublayers Self], // References to other Layers that feed input into this
}
If I define structs at the module level, I can reference not-yet defined structs.
struct S {
ComesLater c;
}
struct ComesLater {}
But If I do the same inside an unittest or a function block, it doesn't work:
unittest {
struct S {
ComesLater c;
}
struct ComesLater {}
}
Error: undefined identifier 'ComesLater'
Why is that? How can I get order-independent declarations inside functions? Is there some kind of forward-declaration in d? I need this because I generate structs using mixin and ordering the declarations in the order of their inner-dependencies would be quite some effort, sometimes impossible, if there are circularly referencing structs. (using pointers.)
Declarations inside functions, unittests, or anywhere else that statements can actually be executed are indeed order-dependent because their values may depend on the code before them running. Think of a local variable:
int a;
writeln(a);
a = b;
int b = get_user_line();
If order wasn't important there, when would the two functions get called? Would the user be asked for a line before the writeln as the declarations are rewritten?
The current behavior of making b an undefined variable error keeps it simple and straightforward.
It works independent of order in other contexts because there is no executable code that it can depend on, so there's no behavior that can change if the compiler needs to internally think about it differently.
So:
How can I get order-independent declarations inside functions?
Change the context such that there is no executable code... put it all inside another struct!
void main() { // or unittest { }
struct Holder {
static struct S {
C c;
}
static struct C {}
}
}
Since execution happens around the holder and doesn't happen inside it, the order of declaration inside doesn't matter again. Since you can define almost anything inside a struct, you can use this for variables, functions, other structs, and so on. Basically all you have to do is wrap your existing code inside the struct Holder {} brackets.
By making everything static inside, you can just use it like a container and reference the stuff with Holder.S, etc., on the outside.
A logging structure that depends on logging related functions looks like this:
typedef struct
{
TFkt_vlogf vlogf;
TFkt_outf outf;
void* logData;
} TLogger;
In this logging function there is an abstract logData that is assigned with different pointers depending on the job that the logger has.
A Filelogger would at one point access a stored filehandle like this.
FILE * fileHandle = (FILE *)(logger->logData);
Although this compiles SPLint is unhappy about this and complains with this message:
Cast to underlying abstract type FILE *: (FILE *)(logger->logData)
What can i do to satisfy SPLint?
i tried to sprinkle some /*#abstract#*/ around but it did not help
Is there a better way in C90 to store and access data while still keeping the structure signature to pass the type around independent of its implementation?
The better Solution is to use a union and have all possible Data inside that union.
typedef union
{
FILE * fileHandle;
char something;
long int other;
} TLog_data;
typedef struct
{
TFkt_vlogf vlogf;
TFkt_outf outf;
TLog_data logData;
} TLogger;
At some point during execution you would use:
((TLogger*) logger)->logData.fileHandle
i have a structure defined, which contains a public field and a public property named _one and One respectively, now i instantiate the struct in the main function (not creating new object), and called the Property from the struct, i am getting the compile time error saying use of unassigned local variable One, however when i called the field _one, it works pretty expected here what i am doing:
public struct myStruct
{
public int _one;
public int One
{
get { return _one; }
set { _one = value; }
}
public void Display()
{
Console.WriteLine(One);
}
}
static void Main(string[] args)
{
myStruct _struct;
_struct.One = 2; // Does not works
_struct._one = 2; // Works fine
}
can anyone explain whats the reason behind this, could not understand the concept.
You need to initialize the struct in order for the property to be accessible - _struct has a default value otherwise:
myStruct _struct = new myStruct();
By the way - mutable value types are evil.
This is unintuitive behavior, but it is permitted by the rules of Definite assignment checking. Described in excruciating detail in section 5.3 of the C# Language Specification. The key phrase, early in the chapter is:
In additional to the rules above, the following rules apply to struct-type variables and their instance variables:
- An instance variable is considered definitely assigned if its containing struct-type variable is considered definitely assigned.
- A struct-type variable is considered definitely assigned if each of its instance variables is considered definitely assigned.
It is the latter rule that permits this. In other words, you can also initialize a struct by assigning all of its variables. You can see this by trying these snippets:
myStruct _struct = new myStruct();
_struct.Display(); // fine by the 1st bullet
myStruct _struct;
_struct.Display(); // bad
myStruct _struct;
_struct._one = 2;
_struct.Display(); // fine by the 2nd bullet
So you don't get CS0165 by assigning the field because that would disallow initializing the structure by assigning its variables.
The reasons which would favor using read-write properties instead of exposed fields in class definitions do not apply to structures, since they can support neither inheritance nor update notifications, and the mutability of a struct's field depends upon the mutability of the struct instance, regardless of whether the field is exposed or not. If a struct is supposed to represent a group of related but freely-independently-modifiable variables, it should simply expose those variables as fields. If a property with a backing field is supposed to be read-only, the constructor should set the backing field directly, rather than via property setter.