query to detect ISP violations - ndepend

I am trying to create a special query with NDepend, but cannot figure it out.
Here's what I'd like to query in a more procedural pseudocode:
var list
foreach type t
foreach i = t.attribute that is an interface
var nm = i.numberOfMethods
var mu = numberOfMethods that t actually uses
if mu / nm < 1
list.Add(t)
end foreach
end foreach
return list
It's supposed to list types that don't comply with the Interface Segregation Principle.
Thanks!

So the query you ask can be written this way:
from t in JustMyCode.Types where !t.IsAbstract
from i in t.TypesUsed where i.IsInterface
// Here collect methods of i that are not used
let methodsOfInterfaceUnused = i.Methods.Where(m => !m.IsUsedBy(t))
where methodsOfInterfaceUnused.Count() > 0
select new { t, methodsOfInterfaceUnused }
This query has the peculiarity to match several time a same type, one for each time methodsOfInterfaceUnused is not empty. The result is then nicely presented and understandable:

Related

A cleaner way to pass many parameters into many functions in a script, without moving to object-oriented code structure?

I am looking for some style/best practice advice. I often find myself writing scripts which need many (several tens of) parameters to be defined at the beginning. Then these parameters are used by many functions within the script. A minimum, simplified example might look something like the following:
params.var1 = 1;
params.var2 = 10;
params.var3 = 100;
params.var4 = 1e3;
result1 = my_func1(params);
result2 = my_func2(params);
Now, I don't want to pass many inputs into every function, so am reluctant to do something like result1 = my_func1(var1,var2,var3,var4,...). Therefore, I always find myself making each variable a field of a structure (e.g. params), and then passing this structure alone into each function, as above. The structure is not modified by the functions, only the parameters are used for further calculations.
One of the functions might look like this then:
function result = my_func1(params)
var1 = params.var1;
var2 = params.var2;
var3 = params.var3;
var4 = params.var4;
result = var1.^2 + var2.^2 -var3.^3 + var4;
end
Now, because I don't want to refer to each variable within the function as params.var1, etc. (in the interest of keeping the expression for result as clear as possible), I first do all this unpacking at the beginning using var1 = params.var1.
I suppose the best thing to be doing in situations like this might be to use classes (because I have some data and also want to perform functions on that data). Are there any better ways for me to be doing this kind of thing without moving fully to object-oriented code?
I would simply leave the unpacking out. Call the struct params something shorter inside the function, to keep clutter to a minimum:
function result = my_func1(p)
result = p.var1.^2 + p.var2.^2 - p.var3.^3 + p.var4;
end
I would keep calling it params elsewhere, so you don’t have to deal with cryptic names.
You can define constant functions:
function out = var1
out = 1;
end
function out = var2
out = 10;
end
function result = my_func1
result = var1.^2 + var2.^2;
end
Based on your actual application you may pass array of numbers:
var = [var1 var2 var3 var4];
my_func1(var);
my_func1(var1,var2,var3,var4,...) in my opinion is preferred over passing struct.

How do I pass two parameters to a js object, including an array?

I am completely new to Max and am struggling to understand how to use arrays and Javascript parameters.
I have one working js object that outputs an array:
var inlets = 1;
var outlets = 1;
function getRandomChordProgression()
{
outlet(0, [1,4,5]);
return [1,4,5];
}
And then later I want to use that array in another js object, that takes an array and an integer:
var inlets = 2;
var outlets = 1;
function getCurrentChord(chords, barNumber)
{
var chord = chords[barNumber % 3];
outlet(0, chord);
return chord;
}
I tried the below, but the js gets undefined inputs.
The first thing to notice is that in Max Msp, in order to assign a list to a single symbol, you need to use the "tosymbol" object. Even if lists are effectively considered mono dimensional arrays in Max Msp, in order to be understood by javascript they first need to be converted. Once the list is converted into a symbol, we can join it with the integer coming from the number box, pack it with the getCurrentChord message and feed it into the getCurrentChord.js object.
You will see that by converting a list into a symbol every character in the array, including the spaces, is seen as part of the array. So using your example, an array composed by 3 integers will have 5 positions occupied, from 0 to 4. In order to make this work, inside the second .js script the modulo operator needs to be set to 5 in order to have a maximum remainder of 4. This means that by setting the number box to 1 or 3 you will have an empty output. So you need to decide how and if to parse the input or the output in order to obtain only the values desired.
var inlets = 2;
var outlets = 1;
function getCurrentChord(chords, barNumber)
{
var chord = chords[barNumber % 5];
outlet(0, chord);
}
Hope that helps!

Coffeescript iteration over array of objects does not compile as expected

I would like to perform an iteration over an array of objects. Instead of writing
for item in items
for k, v in item
# Do Something
I would like to do something similar to this
for k,v of item in items
# Do something
Which based on the compiled output is not supported:
var k, ref, ref1, v, indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
ref1 = (ref = indexOf.call(items, item) >= 0) != null ? ref : [];
for (k in ref1) {
v = ref1[k];
# Do something
}
Is there any other comprehension-like operation through which I can perform this shortcut?
EDIT: I can refer to specific keys in the object by doing
for { k1, k2 }, i in items
# Do something
For the sake of the question, assume the keys are dynamic
No you can't. Following coffeescript's golden rule “it's just JavaScript”, consider looking at the source where a for loop gets translated. You will need two Javascript fors and you only can get one from a coffescript for (the for gets inserted in line 2079).
The javascript result you want to have is something like this:
for(_i…;…;…){
var _x = items[_i];
for(k in _x){
var v = _x[k]
…
}}
There are only two ways to get a javascript for loop (apart from the prewritten ones, like in class definitions): On “Range compilation”, which always gives a for(…;…;…) loop (which contructs an array inside a closure that will be returned) and for the for construct.
Your example to access single keys works because you are using some very special case of destructuring assignment. What you would need is a destructuring that extracts key-value pairs and there is none. If you look at the compiled example constructs like this get translated into a=items[i].a so such that there is no iteration. You even can omit the ,i:
for {a} in items
#iterate over the .a values of items
If your #Do something is just one line, you can put your fors on one line, but I personally think it doesn't increase the readability.
console.log [k,v] for k,v of i for i in items

loop starting from given index

Considering the following javascript, what's the best way to write this loop in coffee script, given the initial index is greater than 0:
function mixin(target, source, methods) {
for (var i = 2, l = arguments.length; i < l; i++){
var method = arguments[i];
target[method] = source[method].bind(source)
}
}
Automatic code converters suggest use a while loop like this:
mixin = (target, source, methods) ->
i = 2
l = arguments.length
while i < l
method = arguments[i]
target[method] = source[method].bind(source)
i++
Is there a cleaner way to do this?
You'd usually use a splat in CoffeeScript when defining your mixing function:
The JavaScript arguments object is a useful way to work with functions that accept variable numbers of arguments. CoffeeScript provides splats ..., both for function definition as well as invocation, making variable numbers of arguments a little bit more palatable.
So you'd say:
mixin = (target, source, methods...) ->
# splat ----------------------^^^
for method in methods
target[method] = source[method].bind(source)
and your problem goes away. The splat in the argument list will collect all the arguments after source into a methods array for you so you won't have to worry about arguments at all; the splat also makes the function's signature nice and obvious.
Use an exclusive range (triple dot, excludes the number at the highest.
for i in [2...arguments.length]
method = arguments[i]
target[method] = source[method].bind(source)
If you have 5 things in your args, this will hit indexes 2, 3 and 4.

Access data in structures when field names are unknown

I have data as a struct with several layers, for example:
data.A.B
The data I want to access is in layer B. But the problem is that field names in B can be different depending on where the data comes from. Therefore I can't just type:
data.A.B.myData
myData is itself a struct
I can use:
fieldnames(data.A)
to find the names, but this doesn't help my much. I would have to write code sections for every possible field name that can occur at this level. And that's just what i trying to avoid.
Is there a way to get down to the data I have (myData) without knowing the field names of B?
Traditionally, you can loop over the fieldnames and perform the search of myData at a specific sub-structure of the struct. However, if you don't know which sub-structure you need to search, then you can perform a recursive algorithm. Below is an example. It will return the first match of myData in the struct or an empty matrix if no match found. The code can be improved to find all matches of myData.
function S2=getmyfield(S1,queriedField)
if isstruct(S1)
% Get all fieldnames of S1
fieldArray=fieldnames(S1);
% Find any match with the queried field. You can also use isfield().
% If there is a match return the value of S1.(queriedField),
% else perform a loop and recurse this function.
matchTF=strcmp(queriedField,fieldArray);
if any(matchTF)
S2=S1.(fieldArray{matchTF});
return;
else
S2=[];
i=0; % an iterator count
while isempty(S2)
i=i+1;
S2=getmyfield(S1.(fieldArray{i}),queriedField);
end
end
else
S2=[];
end
end
Cheers.
You just need a recursive function that checks fieldnames at each level for the structure.
This is roughly what you need (it could be improved to supply the path to the found field).
function [ value, found ] = FindField( rootStruct, fieldName )
%FindField - Find a field with a structure
value = [];
found = 0;
if isstruct( rootStruct )
fields = fieldnames(rootStruct);
for fi=1:length(fields)
if strcmp(fields{fi}, fieldName )
value = rootStruct.(fieldName);
found = true;
return;
end
[value, found ] = FindField( rootStruct.(fields{fi}), fieldName );
if found
return;
end
end
end
end
Usage example:
a.b = 1;
a.b.c = 2;
a.b.d = struct('Index',1,'Special',2);
FindField(a,'d')
ans =
Index: 1
Special: 2