CK metrics from C# project with Ndepend - metrics

I have project for school. Now I need to make from it report of all metrics CK (Chidamber Kemerer metrics). The report has to be like table of all those metrics. Question is how to make it from Ndepend this report which it generates it is not what I am looking for.
Please help and say how to do it... maybe some tips, documents or something this is very important...

Ok, so if we are talking of these Chidamber Kemerer metrics, the NDepend ability to write Code Queries and Rules over LINQ queries (CQLinq) will answer all your needs. For example:
WMC Weighted Methods Per Class
warnif count > 0
from t in Application.Types
let methods = t.Methods
.Where(m => !m.IsPropertyGetter &&
!m.IsPropertySetter &&
!m.IsConstructor)
where methods.Count() > 20
orderby methods.Count() descending
select new { t, methods }
DIT Depth of Inheritance Tree
warnif count > 0
from t in JustMyCode.Types
where t.IsClass
let baseClasses = t.BaseClasses.ExceptThirdParty()
where baseClasses.Count() >= 5
select new { t, baseClasses,
// The metric value DepthOfInheritance takes account
// of third-party base classes
t.DepthOfInheritance
}
NOC Number of Children
from t in Types
where t.IsClass
let childClasses = t.DerivedTypes
where childClasses.Count() > 0
orderby childClasses.Count() descending
select new { t, childClasses }
CBO Coupling between Object Classes
from t in Application.Types
let typesUsed = t.TypesUsed.ExceptThirdParty()
orderby typesUsed.Count() descending
select new { t, typesUsed }
and so on...

Does NDepend have a direct way in CQL to measure RFC (RFT)? Or do we have to write a CQL query for recursive counting invoked methods in used classes (types) our-self? If so, how does it look like?

Related

pig - need tips after performance tuning gone wrong

I have a Pig script that took around 10 minutes to finish and I thought that there was still room for some performance improvement.
So, I started by putting the JOINs and GROUPs in a nested FOREACH and also putting the previous FILTERs inside the same FOREACH.
I also added using 'replicated'.
The problem now is that instead of taking 10 minutes, it's taking over 30 minutes.
Is there a place that has best practices and performance improvement tips besides PIG's documentation?
So that you can get a better picture, here's some code:
--before
previous_join = JOIN A by id, B by id --for symplification
filtering = FILTER previous_join BY ((year_min > 1995 ? year_min - 1 : year_min) <= list_year and (year_max > 2015 ? year_max - 1 : year_max) >= list_year);
final_filtered = FOREACH filtering GENERATE user_id as user_id, list_year;
--after
final_filtered = FOREACH (JOIN A by id, B by id) {
tmp = FILTER group BY ((A::year_min > 1995 ? A::year_min - 1 : A::year_min) <= B::list_year and (A::year_max > 2015 ? A::year_max - 1 : A::year_max) >= B::list_year and A::premium == 'true');
GENERATE A::user_id AS user_id, B::list_year AS list_year;
};
Am I doing something wrong or is this the wrong approach?
Thanks.
In prior case [before] you are performing filter and projection after the join is performed.
It will be helpful if you calculate time log for each operation and identify the bottleneck operation.
Can you also try splitting your filter statements in multiple relations rather than just one and check the difference in filter timing?
filter_by_min_year = FILTER previous_join BY ((A::year_min > 1995 ? A::year_min - 1 : A::year_min) <= B::list_year);
filter_by_max_year = FILTER filter_by_min_year BY (A::year_max > 2015 ? A::year_max - 1 : A::year_max) >= B::list_year);
Overall you want to find ids(+some more columns) with A::year_min <=B::list_year and A::year_max >= B::list_year
Instead of performing join on raw A & B, you can try using projections on both of them to contain only columns needed for join and later operations.
A-projected = foreach A generate id, year_min, year_max;
B-projected = foreach B generate id, list_year;
C = join A-projected by id, B-projected by id USING 'replicated';
If any of A-projected or B-projected is a small set that can be loaded in memory use replicated join, I am assuming B-projected to be a smaller set than A-projected.
If this doesnt apply to your case, please skip this option.
Also you can try setting the number of reducers to be used for this join by using PARALLEL keyword.
After applying filter you will get a list of required id's that you can use to fetch other information from A or B.
Also consider tweaking MapReduce properties like io.sort.mb, mapred.job.shuffle.input.buffer.percent etc.
Hope this helps.

linq distinct query?

I need a little help with Linq i have a DB table with restourants tables in it. In the DB i have "TableNumber, Floor , RestaurantID" I would like to get list of all floors. For example if i have this list:
TableNumber, Floor , RestaurantID
10 1 1
11 1 1
12 2 1
13 2 1
14 3 1
I would like to get only "1,2,3".
Right now the method returns all rows.
public IEnumerable<ListPad.Item> GetFloorsListPads(SSF.ART.Key restaurant_id)
{
return from restaurant_floor in EnterpriseTouchRestaurantApplication.TouchRestaurant.AllRestaurantTables
where restaurant_floor.RestaurantID == restaurant_id && restaurant_floor.Active == true
orderby restaurant_floor.Floor
select new ListPad.Item()
{
Color = Color.SkyBlue,
Text = string.Format("{0}", restaurant_floor.Floor),
Tag = restaurant_floor
};
}
Thanks for all the help in advance.
You need either one or two things, depending of whether or not ListPad.Item defines equality (by overriding Equals and GetHashCode) in the way you describe. If so, then adding .Distinct() to your query will give you the distinct items. If not, you can do it one of three ways.
Return an anonymous type, call Distinct on it, and map to the actual type (lazy way)
Implement IEquatable on ListPad.Item, overriding Equals and GetHashCode (you'll need to research how to properly implement GetHashCode so it matches your equality conditions)
Define an IEqualityComparer<ListPad.Item> that defines your equality.
1 is the lazy way but is less coding. 2 is handy if your conditions define equality for ALL uses of ListPad.Item (not just this particular scenario). 3 separates the equality check from the actual type, which is handy if you have other cases where equality would be defined differently.

Linq query returns duplicate results when .Distinct() isn't used - why?

When I use the following Linq query in LinqPad I get 25 results returned:
var result = (from l in LandlordPreferences
where l.Name == "Wants Student" && l.IsSelected == true
join t in Tenants on l.IsSelected equals t.IsStudent
select new { Tenant = t});
result.Dump();
When I add .Distinct() to the end I only get 5 results returned, so, I'm guessing I'm getting 5 instances of each result when the above is used.
I'm new to Linq, so I'm wondering if this is because of a poorly built query? Or is this the way Linq always behaves? Surely not - if I returned 500 rows with .Distinct(), does that mean without it there's 2,500 returned? Would this compromise performance?
It's a poorly built query.
You are joining LandlordPreferences with Tenants on a boolean value instead of a foreign key.
So, most likely, you have 5 selected land lords and 5 tenants that are students. Each student will be returned for each land lord: 5 x 5 = 25. This is a cartesian product and has nothing to do with LINQ. A similar query in SQL would behave the same.
If you would add the land lord to your result (select new { Tenant = t, Landlord = l }), you would see that no two results are actually the same.
If you can't fix the query somehow, Distinct is your only option.

Is there an OR clause in LINQ?

I am trying to query an XML document for the specific records that I need. I know that the line containing the "or where" case below is incorrect, but I'm hoping it will illustrate what I am trying to accomplish. Can you do a conditional where clause on two seperate properties?
XDocument xd = XDocument.Load("CardData.xml");
SearchList.ItemsSource = from x in xd.Descendants("card")
where x.Element("title").Value.ToUpper().Contains(searchterm.ToUpper())
or where x.Element("id").Value.Contains(searchterm)
select new Card
{
Title = x.Element("title").Value
};
Yes - simply use the boolean or || and combine your conditions into one Where clause:
where x.Element("title").Value.ToUpper().Contains(searchterm.ToUpper()) ||
x.Element("id").Value.Contains(searchterm)
Also note just as a minor optimization, I would pre-compute some of the operations you currently have in your Where clause so they are not performed on every item in the list - probably doesn't matter but it might when you have a lot of elements (and is just a good habit to get into in my opinion):
string searchTermUpperCase = searchterm.ToUpper();
SearchList.ItemsSource = from x in xd.Descendants("card")
where x.Element("title").Value.ToUpper().Contains(searchTermUpperCase)
or where x.Element("id").Value.Contains(searchterm)
..

Using Linq to bring back last 3,4...n orders for every customer

I have a database with customers orders.
I want to use Linq (to EF) to query the db to bring back the last(most recent) 3,4...n orders for every customer.
Note:
Customer 1 may have just made 12 orders in the last hr; but customer 2 may not have made any since last week.
I cant for the life of me work out how to write query in linq (lambda expressions) to get the data set back.
Any good ideas?
Edit:
Customers and orders is a simplification. The table I am querying is actually a record of outbound messages to various web services. It just seemed easer to describe as customers and orders. The relationship is the same.
I am building a task that checks the last n messages for each web service to see if there were any failures. We are wanting a semi real time Health status of the webservices.
#CoreySunwold
My table Looks a bit like this:
MessageID, WebserviceID, SentTime, Status, Message, Error,
Or from a customer/order context if it makes it easer:
OrderID, CustomerID, StatusChangedDate, Status, WidgetName, Comments
Edit 2:
I eventually worked out something
(Hat tip to #StephenChung who basically came up with the exact same, but in classic linq)
var q = myTable.Where(d => d.EndTime > DateTime.Now.AddDays(-1))
.GroupBy(g => g.ConfigID)
.Select(g =>new
{
ConfigID = g.Key,
Data = g.OrderByDescending(d => d.EndTime)
.Take(3).Select(s => new
{
s.Status,
s.SentTime
})
}).ToList();
It does take a while to execute. So I am not sure if this is the most efficient expression.
This should give the last 3 orders of each customer (if having orders at all):
from o in db.Orders
group o by o.CustomerID into g
select new {
CustomerID=g.Key,
LastOrders=g.OrderByDescending(o => o.TimeEntered).Take(3).ToList()
}
However, I suspect this will force the database to return the entire Orders table before picking out the last 3 for each customer. Check the SQL generated.
If you need to optimize, you'll have to manually construct a SQL to only return up to the last 3, then make it into a view.
You can use SelectMany for this purpose:
customers.SelectMany(x=>x.orders.OrderByDescending(y=>y.Date).Take(n)).ToList();
How about this? I know it'll work with regular collections but don't know about EF.
yourCollection.OrderByDescending(item=>item.Date).Take(n);
var ordersByCustomer =
db.Customers.Select(c=>c.Orders.OrderByDescending(o=>o.OrderID).Take(n));
This will return the orders grouped by customer.
var orders = orders.Where(x => x.CustomerID == 1).OrderByDescending(x=>x.Date).Take(4);
This will take last 4 orders. Specific query depends on your table / entity structure.
Btw: You can take x as a order. So you can read it like: Get orders where order.CustomerID is equal to 1, OrderThem by order.Date and take first 4 'rows'.
Somebody might correct me here, but i think doing this is linq with a single query is probably very difficult if not impossible. I would use a store procedure and something like this
select
*
,RANK() OVER (PARTITION BY c.id ORDER BY o.order_time DESC) AS 'RANK'
from
customers c
inner join
order o
on
o.cust_id = c.id
where
RANK < 10 -- this is "n"
I've not used this syntax for a while so it might not be quite right, but if i understand the question then i think this is the best approach.

Resources