What would be the best way of reusing uvm sequences for different environment - verification

Let's say I have a DUT (e.g. l2 cache) with AXI bus in master port and I have created a class AXI_transfer extended from sequence_item, 100 sequences of interesting test scenarios and a uvm driver. Now, the bus protocol of DUT has changed from AXI to AHB. Testbench components that need to be modified are the sequence_item, and the driver (because they are protocol dependent). Now, I don't like to redevelop sequences for AHB because they are transaction level scenarios. Instead, I'd like to reuse all my sequences tied to AXI_transfer items. What would be the best methodology?
My idea is that I define a base_transfer extended from sequence_item and extend AXI_transfer and AHB_transfer from this base_transfer. Also, I modify all my sequences to be parameterized with this base_transfer type. Now, in my uvm test, I can do
base_transfer::type_id::set_type_override( AXI_transfer::get_type());
if I need to use AXI_transfer or
base_transfer::type_id::set_type_override( AHB_transfer::get_type());
if I need to use AHB_transfer. For driver, I need to develop two drivers -- one for AXI and the other for AHB.
Do you think this would work? If not what other methods are recommended?

In general, I believe you seek a LAYERED approach. Your upper layer simply sends and receives abstract traffic. It's up to the lower layer to handle details of the protocol.
This is exactly the approach used by the uvm_register_adapter. See something like this: http://cluelogic.com/2012/10/uvm-tutorial-for-candy-lovers-register-abstraction
In practice, what is causing you to have a hundred different sequences for an interface? The things that are causing you to create additional sequences are quite likely the kind of things that will cause difficulty translating between protocols. Your AXI/ACE will certainly use memory barriers, but how are you going to create them on an AHB interface, for instance?

Related

May a Repository call an UseCase in Clean Architecture?

This is a very tricky question, because when we check the rules it's not explicit that a repository couldn't call an UseCase. However, it doesn't seem logical.
Is there any definition/good practices and why it shouldn't do this?
Thanks!
The short answer is "No" - it shouldn't, regardless of the context (in most of all cases). As to why - the definitions, principles and good practices - it may be helpful to think in terms of clear separation of concerns across your whole Clean Architecture implementation.
Consider this illustration, as background at thinking about how one could organize the interactions (and dependencies) between main parts of a Clean Architecture.
The main principles illustrated are, that -
Through its execution, the Use Case has different "data needs" (A and B). It doesn't implement the logic to fulfill them itself (since they require some specific technology). So the Use Case declares these as two Gateway-interfaces ("ports"), in this example. And then calls them amidst its logic.
Both of these interfaces declare some distinct set of operations that should be provided (implemented) from "outside". The Use Case, in its logic, needs and invokes all of those A and B operations. They are separated into A and B, because they are different kinds of responsibilities - and might be implemented by different parts of the system (but not necessarily). Let's say that the Use Case needs loading of persisted domain objects (as part of A operations), but it also needs to retrieve configuration (as some key-value pairs), which are B operations. These interfaces are segregated since both sets of operations serve distinct purposes for the Use Case. Anyhow, it's important design-wise, that they both explicitly "serve" the Use Case needs - meaning, they are not generic entity-centric DAO / Repository interfaces; they ONLY have operations that the Use Case actually needs and invokes, in exactly the shape and form (parameters, return values) that the Use Case specifically needs them. They are "ports" to be "plugged into", as part of the whole Use Case.
The "outside" providers of these responsibilities are the Adapters (the implementers) of those needs. To fulfill them, they typically use some specific technology or framework - a database, a network call to some server, a message producer, a file operation, Spring's configuration properties, etc.
The Use Case is invoked (called) only by Drivers side of the architecture (that is, the initiating side). The Use Case itself, in fact, is one of the "initiators" for its further collaborating parts (eg, the Adapters).
On the other hand, the Use Case is "technically supported" (the declared parts of its needs "implemented") by Adapters side of the architecture.
Effectively, there is a clear separation of who calls what - meaning, at runtime the call stack progresses in a clear directional flow of control across this architecture.
The flow of control is always from Drivers towards Adapters (via the Use Case), never the other way around.
These are principles I have learned, researched, implemented and corrected purely across my career in different projects. In other words, they've been shaped by the real world in terms of what has been practical and useful - in terms of separation of concerns and clear division of responsibilities - in my experience. Yours naturally may differ, and there is no universal fit - CA is not a recipe, it is a mindset of software design, implementable in (better and worse) several ways.
Thinking simply though, I would imagine in your situation Repository is your "data storage gateway" implementation of the Use Case's (Data) Gateway. The UC needs that data from "somewhere" - without caring where it comes from or how its is stored. This is very important - the whole core domain, along with the Use Case needs to be framework and I/O agnostic.
Your Repository fulfills that need - provides persisted domain objects. But the Use Case must not call it directly, instead it declares a Gateway (in Hexagonal eg Ports & Adapters architecture, named a Port) - with needed operation(s) that your Repository needs to implement. By using some specific (DB / persistence) technology, your Repository fulfills it -it implements one of the Use Case's "ports", as an Adapter.
With the above being said - on rare occasions, some Gateway implementations may demand exceptions. They might need several back-and-forth-going interactions, even across your architecture. They are rare and indeed complex situations - likely not necessary for a Repository implementation.
But, if that is really an inevitable case - then it's best if the Use Case, when calling the Gateway, provides a callback
interface as a parameter of the call. So during its processing the Gateway's implementer can call back using the operations in that interface - effectively implementing the back-and-forth necessity. In most of all cases though, this implies excessive logic and complexity at the adapters' level, which should be avoided - and serves as a strong cue that the current solution should be re-designed.

Deciding extent of coupling

I have a Component which has API exposed with some 10 functionality in all. I can think of two ways to achieve it:
Give out all these functionality as separate functions.
Expose only one function which takes an XML as input. Based on request_Type specified and the parameters passed in the XML, I internally call one of the respective functions.
Q1. Will the second design be more loosely coupled than the first ?
I always read about how I should try my components to be loosely coupled, should I really go to this extent to achieve lose coupling ?
Q2. Which one of these would be a better design in terms of OOP and why?
Edit:
If I am exposing this API over D-Bus for others to use, will type checking still be a consideration to compare the two approaches? From what I understand type checking is done at compile time, but in case when this function is exposed over some IPC, issue of type checking comes into picture ?
The two alternatives you propose do not differ in the (obviously quite large) number of "functions" you want to offer from your API. However, the second seems to have many disadvantages because you are loosing any strong type checking, it will become much harder to document the functionality etc. (The only advantage I see is that you don't need to change your API if you add functionality. But at the disadvantage that users will not be able to figure out API changes like deleted functions until run-time.)
What is more related with this question is the Single Responsiblity Principle (http://en.wikipedia.org/wiki/Single_responsibility_principle). As you are talking about OOP, you should not expose your tens of functions within one class but split them among different classes, each with a single responsibility. Defining good "responsibilities" and roles requires some practice, but following some basic guidelines will help you to get started quickly. See Are there any rules for OOP? for a good starting point.
Reply to the question edit
I haven't used D-Bus, so this might be totally wrong. But from a quick look at the tutorial I read
Each object supports one or more interfaces. Think of an interface as
a named group of methods and signals, just as it is in GLib or Qt or
Java. Interfaces define the type of an object instance.
DBus identifies interfaces with a simple namespaced string, something
like org.freedesktop.Introspectable. Most bindings will map these
interface names directly to the appropriate programming language
construct, for example to Java interfaces or C++ pure virtual classes.
As far as I understand, D-Bus has the concept of differnt objects which provide interfaces consisting of several methods. This means (to me) that my answer above still applies. The "D-Bus native" way of specifying your API would mean to exhibit interfaces and I don't see any reason why good OOP design guidelines shouldn't be valid, here. As D-Bus seems to map these even to native language constructs, this is even more likely.
Of course, nobody keeps you from just building your own API description language in XML. However, things like are some kind of abuse of underlying techniques. You should have good reasons for doing such things.

What does 'low in coupling and high in cohesion' mean

I have problems understanding the statement low in coupling and high in cohesion. I have googled and read a lot about this, but still finding it hard to understand.
To what I understand is High cohesion means, that we should have classes that are specialized to perform a particular function. Hope this is correct? Like a credit card validation class, which is specialized to validate credit cards only.
And still don't understand what low Coupling means?
What I believe is this:
Cohesion refers to the degree to which the elements of a module/class belong together, it is suggested that the related code should be close to each other, so we should strive for high cohesion and bind all related code together as close as possible. It has to do with the elements within the module/class.
Coupling refers to the degree to which the different modules/classes depend on each other, it is suggested that all modules should be independent as far as possible, that's why low coupling. It has to do with the elements among different modules/classes.
To visualize the whole picture will be helpful:
The screenshot was taken from Coursera.
Cohesion in software engineering, as in real life, is how much the elements consisting a whole(in our case let's say a class) can be said that they actually belong together. Thus, it is a measure of how strongly related each piece of functionality expressed by the source code of a software module is.
One way of looking at cohesion in terms of OO is if the methods in the class are using any of the private attributes.
Now the discussion is bigger than this but High Cohesion (or the cohesion's best type - the functional cohesion) is when parts of a module are grouped because they all contribute to a single well-defined task of the module.
Coupling in simple words, is how much one component (again, imagine a class, although not necessarily) knows about the inner workings or inner elements of another one, i.e. how much knowledge it has of the other component.
Loose coupling is a method of interconnecting the components in a system or network so that those components, depend on each other to the least extent practically possible…
I wrote a blog post about this. It discusses all this in much detail, with examples etc. It also explains the benefits of why you should follow these principles.
In software design high cohesion means that class should do one thing and one thing very well. High cohesion is closely related to Single responsibility principle.
Low coupling suggest that class should have least possible dependencies. Also, dependencies that must exist should be weak dependencies - prefer dependency on interface rather than dependency on concrete class, or prefer composition over inheritance .
High Cohesion and low coupling give us better designed code that is easier to maintain.
Short and clear answer
High cohesion: Elements within one class/module should functionally belong together and do one particular thing.
Loose coupling: Among different classes/modules should be minimal dependency.
Low coupling is in the context of two or many modules. If a change in one module results in many changes in other module then they are said to be highly coupled. This is where interface based programming helps. Any change within the module will not impact the other module as the interface (the mean of interaction ) between them has not changed.
High cohesion- Put the similar things together. So a class should have method or behaviors to do related job. Just to give an exaggerated bad example: An implementation of List interface should not have operation related to String. String class should have methods, fields which is relevant for String and similarly, the implementation of List should have corresponding things.
Hope that helps.
Cohesion - how closely related everything is with one another.
Coupling - how everything is connected to one another.
Let's take an example - We want to design a self-driving car.
(1) We need the motor to run properly.
(2) We need the car to drive on its own.
All of the classes and functions in (1) starting the motor and making it run work great together, but do not help the car steer. So we place those classes behind an Engine Controller.
All of the classes and functions in (2) work great to make the car steer, accelerate and brake. They do not help the car start or send gasoline to the pistons. So we place these classes behind its own Driving Controller.
These controllers are used to communicate with all of the classes and functions that are available. The controllers then communicate only with each other. This means I can't call a function in the piston class from the gas pedal class to make the car go faster.
The pedal class has to ask the Driving Controller to talk to the Engine Controller which then tells the piston class to go faster. This allows us programmers to be able to find issues and allows us to combine large programs without worrying. This is because the code was all working behind the controller.
Take the example of an old PC motherboard.
Mouse had its own PS/2 port.
Printer had its own Printer port.
Monitor had its own VGA port.
This meant that a particular port was meant only for a particular device, and for none other.
This is Strong / High Coupling
Since a mouse is used only for operating the cursor and related functionalities, a keyboard for typing keys, etc i.e they perform only the task they are intended for, this is High Cohesion
If a mouse had a few buttons 'a' 'b' 'c' to enter, then it is doing more than what it should, since a keyboard is already performing them, this is Low Cohesion
The outdated usage of exclusive ports was thankfully replaced by a standard (interface) we call USB. This is Loose / Low Coupling
Looking at these physical attributes, it looks obvious that this is how it is supposed to be, but while writing software it is very easy to lose track of what functionality is to be put where, etc. and hence as a reminder, in everything in life, always stick to:
'High Cohesion and Loose Coupling'
Metaphorically, if your cat barks, it has poor cohesion, and if your dog needs a cat by his side to bark, it is highly coupled.
"Dogs bark and cats purr, if they barf your pull request will be rejected"
Long story short, low coupling as I understood it meant components can be swapped out without affecting the proper functioning of a system. Basicaly modulize your system into functioning components that can be updated individually without breaking the system
Do you have a smart phone? Is there one big app or lots of little ones? Does one app reply upon another? Can you use one app while installing, updating, and/or uninstalling another? That each app is self-contained is high cohesion. That each app is independent of the others is low coupling. DevOps favours this architecture because it means you can do discrete continuous deployment without disrupting the system entire.
When I was reading about a microservice. I came across the following things:
Cohesion is a measure of the number of relationships that parts of a component have with each other. High cohesion means that all of the parts that are needed to deliver the component's functionality are included in the component
Coupling is a measure of the number of relationships that one component has with other components in the system. Low coupling means that components do not have many relationships with other components
Inheritance or generalization is an example of high coupling (i.e. high interdependence). What I meant by this is that in inheritance often the parent class defines base functionalities that is used by its child class and change in methods of parent class directly impact its child classes. Hence we can say that there is a greater degree of interdependence between classes.
Realization or using interface is an example of high cohesion (i.e. low interdependence). What this means is that an interface put forward a contract for any class that implements it but each class has the right to implement methods declared in interface in its own way and changes in method declared in one class doesn't affect any other class.
Low Coupling:--
Will keep it very simple.
If you change your module how does it impact other modules.
Example:-
If your service API is exposed as JAR, any change to method signature will break calling API (High/Tight coupling).
If your module and other module communicate via async messages. As long as you get messages, your method change signature will be local to your module (Low coupling).
Off-course if there is change in message format, calling client will need to make some change.
Low Coupling and High Cohesion is a recommended phenomenon.
Coupling means to what extent various modules are interdependent and how the other modules are affected on changing some/considerable functionality of a module. Low coupling is emphasized as the dependency has to be maintained low so that very least/negligible changes are made to other modules.
An example might be helpful. Imagine a system which generates data and puts it into a data store, either a file on disk or a database.
High Cohesion can be achieved by separate the data store code from the data production code. (and in fact separating the disk storage from the database storage).
Low Coupling can be achieved by making sure that the data production doesn't have any unnecessary knowledge of the data store (e.g. doesn't ask the data store about filenames or db connections).
Here is an answer from a bit of an abstract, graph theoretic angle:
Let's simplify the problem by only looking at (directed) dependency graphs between stateful objects.
An extremely simple answer can be illustrated by considering two limiting cases of dependency graphs:
The 1st limiting case: a cluster graphs .
A cluster graph is the most perfect realisation of a high cohesion and low coupling (given a set of cluster sizes) dependency graph.
The dependence between clusters is maximal (fully connected), and inter cluster dependence is minimal (zero).
This is an abstract illustration of the answer in one of the limiting cases.
The 2nd limiting case is a fully connected graph, where everything depends on everything.
Reality is somewhere in between, the closer to the cluster graph the better, in my humble understanding.
From another point of view: when looking at a directed dependency graph, ideally it should be acyclic, if not then cycles form the smallest clusters/components.
One step up/down the hierarchy corresponds to "one instance" of loose coupling, tight cohesion in a software but it is possible to view this loose coupling/tight cohesion principle as a repeating phenomena at different depths of an acyclic directed graph (or on one of its spanning tree's).
Such decomposition of a system into a hierarchy helps to beat exponential complexity (say each cluster has 10 elements). Then at 6 layers it's already 1 million objects:
10 clusters form 1 supercluster, 10 superclusters form 1 hypercluster and so on ... without the concept of tight cohesion, loose coupling, such a hierarchical architecture would not be possible.
So this might be the real importance of the story and not just the high cohesion low coupling within two layers only. The real importance becomes clear when considering higher level abstractions and their interactions.
I think you have red so many definitions but in the case you still have doubts or In case you are new to programming and want to go deep into this then I will suggest you to watch this video,
https://youtu.be/HpJTGW9AwX0
It's just reference to get more info about polymorphism...
Hope you get better understanding with this

Using NSStringFromSelector to send method over a network

I'm currently making a client-client approach on some simulation with objective-c with two computers (mac1 and mac2).
I have a class Client, and every computer has a instance of the "Client" on it (client1,client2). I expect that both clients will be synchronized: they will both be equal apart from memory locations.
When a user presses a key on mac1, I want both client1 and client2 to receive a given method from class Client (so that they are synchronized, i.e. they are the same apart from it's memory location on each mac).
To this approach, my current idea is to make 2 methods:
- (void) sendSelector:(Client*)toClient,...;
- (void) receiveSelector:(Client*)fromClient,...;
sendSelector: uses NSStringFromSelector() to transform the method to a NSString, and send it over the network (let's not worry about sending strings over net now).
On the other hand, receiveSelector: uses NSSelectorFromString() to transform a NSString back to a selector.
My first question/issue is: to what extent is this approach "standard" on networking with objective-c?
My second question:
And the method's arguments? Is there any way of "packing" a given class instance and send it over the network? I understand the pointer's problem when packing, but every instance on my program as an unique identity, so that should be no problem since both clients will know how to retrieve the object from its identity.
Thanks for your help
Let me address your second question first:
And the method's arguments? Is there any way of "packing" a given
class instance and send it over the network?
Many Cocoa classes implement/adopt the NSCoding #protocol. This means they support some default implementation for serializing to a byte stream, which you could then send over the network. You would be well advised to use the NSCoding approach unless it's fundamentally not suited to your needs for some reason. (i.e. use the highest level of abstraction that gets the job done)
Now for the more philosophical side of your first question; I'll rephrase your question as "is it a good approach to use serialized method invocations as a means of communication between two clients over a network?"
First, you should know that Objective-C has a not-often-used-any-more, but reasonably complete, implementation for handling remote invocations between machines with a high level of abstraction. It was called Distributed Objects. Apple appears to be shoving it under the rug to some degree (with good reason -- keep reading), but I was able to find an old cached copy of the Distributed Objects Programming Topics guide. You may find it informative. AFAIK, all the underpinnings of Distributed Objects still ship in the Objective-C runtime/frameworks, so if you wanted to use it, if only to prototype, you probably could.
I can't speculate as to the exact reasons that you can't seem to find this document on developer.apple.com these days, but I think it's fair to say that, in general, you don't want to be using a remote invocation approach like this in production, or over insecure network channels (for instance: over the Internet.) It's a huge potential attack vector. Just think of it: If I can modify, or spoof, your network messages, I can induce your client application to call arbitrary selectors with arbitrary arguments. It's not hard to see how this could go very wrong.
At a high level, let me recommend coming up with some sort of protocol for your application, with some arbitrary wire format (another person mentioned JSON -- It's got a lot of support these days -- but using NSCoding will probably bootstrap you the quickest), and when your client receives such a message, it should read the message as data and make a decision about what action to take, without actually deriving at runtime what is, in effect, code from the message itself.
From a "getting things done" perspective, I like to share a maxim I learned a while ago: "Make it work; Make it work right; Make it work fast. In that order."
For prototyping, maybe you don't care about security. Maybe when you're just trying to "make it work" you use Distributed Objects, or maybe you roll your own remote invocation protocol, as it appears you've been thinking of doing. Just remember: you really need to "make it work right" before releasing it into the wild, or those decisions you made for prototyping expedience could cost you dearly. The best approach here will be to create a class or group of classes that abstracts away the network protocol and wire format from the rest of your code, so you can swap out networking implementations later without having to touch all your code.
One more suggestion: I read in your initial question a desire to 'keep an object (or perhaps an object graph) in sync across multiple clients.' This is a complex topic, but you may wish to employ a "Command Pattern" (see the Gang of Four book, or any number of other treatments in the wild.) Taking such an approach may also inherently bring structure to your networking protocol. In other words, once you've broken down all your model mutation operations into "commands" maybe your protocol is as simple as serializing those commands using NSCoding and shipping them over the wire to the other client and executing them again there.
Hopefully this helps, or at least gives you some starting points and things to consider.
These days it would seem that the most standard way is to package everything up on JSON.

VB.NET Beginner design question

VB.NET, VS 2010, .NET 4
Hello,
I've written an application. I've discovered that it is full of circular references. I would like to rewrite portions of my code to improve its design. I have read about tiered programming and want to implement something like it for my application.
Background: My application is a control program for an industrial machine. It parses a recipe (from an Excel file) which contains timing information and setpoints for the various attached devices. There are three main types of devices: Most are connected through Beckhoff terminals and communicate via TwinCAT (Beckhoff's pseudo-PLC software) and two are RS-232 devices, each with a different communication protocol. I can communicate with the Beckhoff devices via a .NET API provided by Beckhoff. I have written parser classes for the two RS-232 devices. Some of the Beckhoff devices are inputs, some are outputs; some are digital, some are (pseudo-)analog.
I think my problem is that I was trying to wrap my head around OOP while writing the application so I created classes willy-nilly without a clear idea of their hierarchy. At some points, I tried to do what I thought was right by, say, making a "Device" class which was inherited by, say, a "TwinCatDevice" class and a "Rs232Device" class. But then I just stuffed all of the communication code in those classes.
What I'm trying now is creating some communication modules (e.g., UtilTwinCat, UtilRs232) that contain abstract methods like "Connect", "Disconnect", "Read", "Write", etc. Then I'm trying to rewrite my "Device" class and subclasses to use these modules so they don't have to contain any of the (sometimes redundant) communication code.
Here's my question: Would it be good design to create separate classes for each type of communication type? i.e., should I have, say, "TwinCatReadOnlyDigital", "TwinCatReadOnlyAnalog", "TwinCatWriteOnlyDigital", "TwinCatWriteOnlyAnalog", "TwinCatReadWriteDigital", "TwinCatReadWriteAnalog", "Rs232ReadOnlyDigital", etc? Or perhaps some interfaces like IReadOnly, IWriteOnly, IDuplex?
This seems like it can't be the right approach in that I imagine someone who is good at programming wouldn't end up with a billion different classes for every eventuality. Is there some way I could selectively implement an interface on a class at run time? I think that's a stupid question... I'm still trying to wrap my head around why one would use an interface. I'm looking for some basic insight on how to grapple with this type of design problem. Specifically, if you have a lot of "things" that differ slightly, is the best approach to create lots of classes that differ slightly?
Thanks a lot in advance,
Brian
Edit: I just wanted to add, to be clear, there is a finite number of devices whose parameters are known, so it would be straightforward to write classes for all the types I'd need. I just wonder if there's a better approach.
That's not really enough information for any concrete answers, but let me make a few suggestions.
"I'm still trying to wrap my head around why one would use an interface."
Mainly because then you can "program to the interface", that is you needn't care if you're working with a Beckhoff or an RS-232 device - you only care that you can send data to it. Just to make it clear: interfaces don't contain implementations. Classes implementing an interface promise to provide concrete implementations for the functions of the interface.
Instead of IReadOnly, IWriteOnly and IDuplex use two interfaces: IWriteable and IReadable (or whatever names make sense). Duplex classes will implement both interfaces.
The Strategy or more likely the Template method patterns may help you with the slightly different classes. Maybe even simple subclassing, but keep in mind that there's often a simpler, nicer solution.
Don't repeat yourself (DRY): try to find one and only one place for every piece of logic.
Functionality shared by several classes should reside in a superclass or utility classes.
Also, more concrete questions will result in more concrete answers :)