
{"id":330,"date":"2016-04-08T14:34:15","date_gmt":"2016-04-08T13:34:15","guid":{"rendered":"http:\/\/serverdude.dk\/?p=330"},"modified":"2016-04-08T14:34:15","modified_gmt":"2016-04-08T13:34:15","slug":"simple-insights-into-source-code-bases","status":"publish","type":"post","link":"https:\/\/serverdude.dk\/?p=330","title":{"rendered":"Simple insights into source code bases"},"content":{"rendered":"<h2>Does the code base scream the domain?<\/h2>\n<p>I was wondering whether or not it would be possible to use parts of PageRank (<a title=\"PageRank on Wikipedia\" href=\"https:\/\/en.wikipedia.org\/wiki\/PageRank\">https:\/\/en.wikipedia.org\/wiki\/PageRank<\/a>) to gain insights into a code base. If PageRank works on web pages to ascertain what the contents of the page relates to, then likely a similar way could be construed for source code.<\/p>\n<p>The simplest thing that could possibly work?<br \/>\nI chose the n-gram (<a title=\"n-gram on Wikipedia\" href=\"https:\/\/en.wikipedia.org\/wiki\/N-gram\">https:\/\/en.wikipedia.org\/wiki\/N-gram<\/a>) approach &#8211; unigram to be specific. While bi- and tri-grams are better for text, I&#8217;m not so sure for code bases, nevertheless, it could be tested.<\/p>\n<h3>The simple process<\/h3>\n<ul>\n<li>Find all files of a specific language inside the project structure. Likely it would be prudent to examine source and test code independently<\/li>\n<li>Remove all for of new-lines<\/li>\n<li>Tokenize on non alphanumeric entities<\/li>\n<li>Build histogram of these tokens<\/li>\n<\/ul>\n<p>Removing comments and possibly strings would likely be a good idea, but that would require parsing and not just bash.<\/p>\n<p style=\"padding-left: 30px;\">find . -name &#8220;*.java&#8221; -type f | xargs cat | tr -d &#8216;\\n&#8217; | tr -d &#8216;\\r&#8217;| tr -cs &#8216;[:alnum:]&#8217; &#8216;\\n&#8217; | sort | uniq -c  | sort -rn &gt; wordfreq.txt<\/p>\n<p>Looking at gerrit&#8217;s word frequency, we get something along these lines:<\/p>\n<ul>\n<li>27560 import<\/li>\n<li>25092 the<\/li>\n<li>21758 com<\/li>\n<li>21385 google<\/li>\n<li>16615 License<\/li>\n<li>14676 public<\/li>\n<li>14544 gerrit<\/li>\n<li>13553 String<\/li>\n<li>12309 final<\/li>\n<li>11823 return<\/li>\n<li>10431 private<\/li>\n<li>10191 new<\/li>\n<li>9809 if<\/li>\n<li>8940 this<\/li>\n<li>8196 0<\/li>\n<li>7665 in<\/li>\n<li>7225 void<\/li>\n<li>7163 under<\/li>\n<li>6809 a<\/li>\n<li>6590 null<\/li>\n<li>6389 server<\/li>\n<li>6234 client<\/li>\n<li>6185 static<\/li>\n<li>6125 for<\/li>\n<li>6024 2<\/li>\n<li>5965 org<\/li>\n<li>5953 to<\/li>\n<li>5384 or<\/li>\n<li>5212 class<\/li>\n<li>4972 may<\/li>\n<li>4963 Override<\/li>\n<li>4934 name<\/li>\n<li>4923 get<\/li>\n<li>4752 distributed<\/li>\n<li>4666 of<\/li>\n<li>4602 java<\/li>\n<li>4492 throws<\/li>\n<li>4392 n<\/li>\n<li>4164 is<\/li>\n<li>3705 e<\/li>\n<\/ul>\n<p>Reading it <em>&#8220;import the com google License public gerrit String final return private new if this 0 in void under a null server client static for 2 org to or class may Override name get distributed of java throws n is e&#8221;<\/em> doesn&#8217;t quite make sense. Clearly the &#8220;License&#8221; and namespace &#8220;com.google&#8221; influences heavily.<\/p>\n<p>Removing the keywords we get:<br \/>\n<em> &#8220;the com google License gerrit 0 in under a server client 2 org to or may name get distributed of n is e&#8221;<\/em><\/p>\n<p>It is not as if the source code really screams what gerrit is about. From Chinese Whisper reconstruction I get something about a <em>&#8220;client server with name distribution&#8221;<\/em> &#8211; not quite the <em>&#8220;Gerrit provides web based code review and repository management for the Git version control system&#8221;<\/em> tagline.<\/p>\n<p>The frequency count drops rapidly &#8211; let&#8217;s pull the data into R to see if there are some patterns.<\/p>\n<p style=\"padding-left: 30px;\">gerrit &lt;- read.table(&#8220;wordfreq.txt&#8221;, header=F)<br \/>\nf &lt;- as.data.frame(table(gerrit$V1))<br \/>\nf$Var1 &lt;- as.numeric(as.character(f$Var1))<br \/>\nplot(log(f), type=&#8221;l&#8221;, xlab=&#8221;log(frequency)&#8221;, ylab=&#8221;log(count)&#8221;, main =&#8221;Gerrit source code tokens\\nlog-log plot&#8221;)<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-332\" title=\"gerrit loglog plot\" src=\"http:\/\/serverdude.dk\/wp-content\/uploads\/gerrit-loglog-plot.png\" alt=\"gerrit loglog plot\" width=\"597\" height=\"523\" srcset=\"https:\/\/serverdude.dk\/wp-content\/uploads\/gerrit-loglog-plot.png 597w, https:\/\/serverdude.dk\/wp-content\/uploads\/gerrit-loglog-plot-300x262.png 300w\" sizes=\"auto, (max-width: 597px) 100vw, 597px\" \/><\/p>\n<p>This seems to be a power law distribution, but with a lot of outliers above 7 (corresponding to around 1100) &#8211; and with an anomaly just short of 8 (corresponding to 2374 to be exact). This is quite likely the template License.<\/p>\n<p style=\"padding-left: 30px;\">gerrit[gerrit$V1 == 2374,]<br \/>\nV1         V2<br \/>\n101 2374     Unless<br \/>\n102 2374   Licensed<br \/>\n103 2374    LICENSE<br \/>\n104 2374        law<br \/>\n105 2374  governing<br \/>\n106 2374    express<br \/>\n107 2374 CONDITIONS<br \/>\n108 2374 compliance<br \/>\n109 2374      BASIS<br \/>\n110 2374     agreed<\/p>\n<p>Plotting the more conformant data<\/p>\n<p style=\"padding-left: 30px;\">k &lt;- f[f$Var1 &lt;1100,]<br \/>\nplot(log(k), type=&#8221;l&#8221;, xlab=&#8221;log(frequency)&#8221;, ylab=&#8221;log(count)&#8221;, main =&#8221;Gerrit source code tokens\\nfrequency &lt; 1100\\nlog-log plot&#8221;)<br \/>\nabline(glm(log(k$Freq ) ~ log(k$Var1)), col=&#8221;red&#8221;)<\/p>\n<p style=\"padding-left: 30px;\">glm(log(k$Freq ) ~ log(k$Var1))<\/p>\n<p style=\"padding-left: 30px;\">Call:  glm(formula = log(k$Freq) ~ log(k$Var1))<\/p>\n<p style=\"padding-left: 30px;\">Coefficients:<br \/>\n(Intercept)  log(k$Var1)<br \/>\n8.554       -1.372<\/p>\n<p style=\"padding-left: 30px;\">Degrees of Freedom: 495 Total (i.e. Null);  494 Residual<br \/>\nNull Deviance:\t    1299<br \/>\nResidual Deviance: 152.9 \tAIC: 829.7<\/p>\n<p style=\"padding-left: 30px;\">exp(8.554\/1.372)<br \/>\n[1] 510.1444<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-333\" title=\"gerrit loglog &lt; 1100\" src=\"http:\/\/serverdude.dk\/wp-content\/uploads\/gerrit-loglog-lt-1100.png\" alt=\"gerrit loglog &lt; 1100\" width=\"597\" height=\"523\" srcset=\"https:\/\/serverdude.dk\/wp-content\/uploads\/gerrit-loglog-lt-1100.png 597w, https:\/\/serverdude.dk\/wp-content\/uploads\/gerrit-loglog-lt-1100-300x262.png 300w\" sizes=\"auto, (max-width: 597px) 100vw, 597px\" \/><\/p>\n<p>So, we should likely look at values with the frequency in this area to get a better suggestion for what the code base is used for.<\/p>\n<p style=\"padding-left: 30px;\">gerrit[gerrit$V1 &lt; 600 &amp; gerrit$V1 &gt;= 500,]<br \/>\nV1             V2<br \/>\n240 598           code<br \/>\n241 597            url<br \/>\n242 592             rw<br \/>\n243 590         values<br \/>\n244 589          label<br \/>\n245 581         plugin<br \/>\n246 580              v<br \/>\n247 563            ctx<br \/>\n248 561         Result<br \/>\n249 558           Util<br \/>\n250 550           UUID<br \/>\n251 544           2013<br \/>\n252 541           bind<br \/>\n253 538             cb<br \/>\n254 533 IdentifiedUser<br \/>\n255 532            err<br \/>\n256 531              u<br \/>\n257 530              o<br \/>\n258 528      substring<br \/>\n259 526         master<br \/>\n260 525     Repository<br \/>\n261 522    CurrentUser<br \/>\n262 522             as<br \/>\n263 521            res<br \/>\n264 520            dom<br \/>\n265 517   assertEquals<br \/>\n266 516          token<br \/>\n267 508          start<br \/>\n268 508      RESOURCES<br \/>\n269 508      interface<br \/>\n270 507           lang<br \/>\n271 506        servlet<br \/>\n272 500         Object<\/p>\n<p>This has a better match with the core of the project, though we still see comment debris, e.g. &#8220;2013&#8221;<\/p>\n<p>Gerrit can be found at <a title=\"Gerrit source code\" href=\"https:\/\/gerrit.googlesource.com\/gerrit\/\">https:\/\/gerrit.googlesource.com\/gerrit\/<\/a> &#8211; I was looking at the codebase from 02bafe0f4c51aa24b2b05d4d1309ecfc828762c0 (January 20th, 2016)<\/p>\n<h2>Independence check<\/h2>\n<p>With the previous information &#8211; and the notion of a vector representation &#8211; I thought about the possibility to check for independence.<\/p>\n<p>If two vectors are independent, then they should be orthogonal. If two code bases are independent, then they should be orthogonal in their domain vectors. To test this, we can try to plot the words used in the code bases. Naturally, we would need to strip away the language keywords, but as we will see, this is not quite as necessary as expected. We can even gain other insights by looking at the keyword uses.<\/p>\n<p>So, as above, I created word frequence files for two JavaScript projects.<\/p>\n<p style=\"padding-left: 30px;\">p1 &lt;- read.table(&#8220;p1-wordfreq.txt&#8221;, header=F)<br \/>\np2 &lt;- read.table(&#8220;p2-wordfreq.txt&#8221;, header=F)<\/p>\n<p>We don&#8217;t really want the exact count, so we pick the relative frequencies<\/p>\n<p style=\"padding-left: 30px;\">p1$V1 &lt;- p1$V1\/max(p1$V1)<br \/>\np2$V1 &lt;- p2$V1\/max(p2$V1)<\/p>\n<p>Now, we only want to look at the tokens they have in common to see whether or not they are orthogonal &#8211; the tokens not common are already orthogonal.<\/p>\n<p style=\"padding-left: 30px;\">common &lt;- merge(p1, p2, by = &#8220;V2&#8221;)<\/p>\n<p style=\"padding-left: 30px;\">plot(common$V1.x, common$V1.y, xlab=&#8221;p1&#8243;, ylab=&#8221;p2&#8243;, main=&#8221;Comparing p1 and p2&#8243;)<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-334\" title=\"comparing JavaScript projects p1 and p2\" src=\"http:\/\/serverdude.dk\/wp-content\/uploads\/comparing-projects-p1-p2.png\" alt=\"comparing JavaScript projects p1 and p2\" width=\"597\" height=\"523\" srcset=\"https:\/\/serverdude.dk\/wp-content\/uploads\/comparing-projects-p1-p2.png 597w, https:\/\/serverdude.dk\/wp-content\/uploads\/comparing-projects-p1-p2-300x262.png 300w\" sizes=\"auto, (max-width: 597px) 100vw, 597px\" \/><\/p>\n<p>Next, we want to identify the JavaScript keywords.<\/p>\n<p style=\"padding-left: 30px;\">js &lt;- read.table(&#8220;JavaScriptKeywords.txt&#8221;, header=F)<br \/>\nnames(js) &lt;- &#8220;V2&#8243; # js is a single column, we want to merge on the keywords in the same column names<br \/>\njs2 &lt;- merge(js, common, by=&#8221;V2&#8243;)<br \/>\npoints(js2$V1.x, js2$V1.y, pch=19, col=&#8221;red&#8221;)<\/p>\n<p style=\"padding-left: 30px;\"># mark the 20% in both directions, thus we get a Pareto segmentation<br \/>\nabline(h=.2, col=&#8221;blue&#8221;)<br \/>\nabline(v=.2, col=&#8221;blue&#8221;)<\/p>\n<p style=\"padding-left: 30px;\">high &lt;- common[common$V1.x &gt; .2 &amp; common$V1.y &gt; .2,]<\/p>\n<p>The most frequently used non-keywords:<\/p>\n<p style=\"padding-left: 30px;\">high[-(match(intersect(high$V2, js2$V2), high$V2)),]<br \/>\nV2      V1.x      V1.y<br \/>\n34      data 0.4170306 0.2444444<br \/>\n49       err 0.5545852 0.4555556<br \/>\n50     error 0.3013100 0.8000000<br \/>\n115 censored 0.6812227 0.6888889<br \/>\n131 settings 0.2052402 0.2111111<\/p>\n<p>The second to last in this list has been censored, it does provide an indication that the projects aren&#8217;t quite independent. The error, err, and data are so common and nondescript that it is somewhat okay to find them in this area, though I&#8217;d rather have less callback functions and better names in general.<\/p>\n<p>The most frequently used keywords:<\/p>\n<p style=\"padding-left: 30px;\">high[(match(intersect(high$V2, js2$V2), high$V2)),]<br \/>\nV2      V1.x      V1.y<br \/>\n47      else 0.3449782 0.4444444<br \/>\n65  function 1.0000000 0.8000000<br \/>\n72        if 0.4716157 0.5000000<br \/>\n154      var 1.0000000 0.6444444<\/p>\n<p>Again this can be explained by a lot of callbacks, which are often on the form:<\/p>\n<p style=\"padding-left: 30px;\">function(err, data) {<br \/>\nif(err){<br \/>\n} else {<br \/>\n}<br \/>\n}<\/p>\n<p>Another explanation could be lots of anonymous functions, though usually callback.<\/p>\n<h2>Conclusion<\/h2>\n<p>Removing comments and imports should provide for a better picture of the code base. Even so, it seems to not exactly scream the domain or architecture.<\/p>\n<p>Bi-grams could be another improvement.<\/p>\n<p>Independence check of supposedly independent projects may reveal that they aren&#8217;t or that the code is skewed towards an unwanted design.<\/p>\n<p>It is far from perfect, but as always it brings a different way of looking at the code base, and it is relatively quick to do.<\/p>\n<p>Comparing large code bases somewhat defeats the purpose as regression to the mean tells nothing much of interest. Taking Gerrit as an example, then the most used token is &#8220;import&#8221;, which is used 27560 times and as we saw above, the interesting parts reveal themselves around 1100 uses, which is less than 4%.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-335\" title=\"comparing gerrit to dotCMS\" src=\"http:\/\/serverdude.dk\/wp-content\/uploads\/comparing-gerrit-dotcms.png\" alt=\"comparing gerrit to dotCMS\" width=\"597\" height=\"523\" srcset=\"https:\/\/serverdude.dk\/wp-content\/uploads\/comparing-gerrit-dotcms.png 597w, https:\/\/serverdude.dk\/wp-content\/uploads\/comparing-gerrit-dotcms-300x262.png 300w\" sizes=\"auto, (max-width: 597px) 100vw, 597px\" \/><img loading=\"lazy\" decoding=\"async\" class=\"aligncenter size-full wp-image-336\" title=\"comparing gerrit to dotCMS (loglog)\" src=\"http:\/\/serverdude.dk\/wp-content\/uploads\/comparing-gerrit-dotcms-loglog.png\" alt=\"comparing gerrit to dotCMS (loglog)\" width=\"597\" height=\"523\" srcset=\"https:\/\/serverdude.dk\/wp-content\/uploads\/comparing-gerrit-dotcms-loglog.png 597w, https:\/\/serverdude.dk\/wp-content\/uploads\/comparing-gerrit-dotcms-loglog-300x262.png 300w\" sizes=\"auto, (max-width: 597px) 100vw, 597px\" \/><\/p>\n<p>Comparing Gerrit and an old repo I had of dotCMS, we find that the most used keywords including entities in java.lang are:<\/p>\n<p style=\"padding-left: 30px;\">import<br \/>\nString<br \/>\npublic<br \/>\nreturn<br \/>\nif<br \/>\nnew<br \/>\nthis<br \/>\nnull<br \/>\nprivate<br \/>\nvoid<br \/>\nstatic<\/p>\n<p>Which could indicate a lot of String constants and conditional logic (with return statements instead of else clauses), and with a possibility of Primitive Obsession &#8211; well, the web does call for a lot of String use.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Does the code base scream the domain? I was wondering whether or not it would be possible to use parts of PageRank (https:\/\/en.wikipedia.org\/wiki\/PageRank) to gain insights into a code base. If PageRank works on web pages to ascertain what the contents of the page relates to, then likely a similar way could be construed for [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[6,10],"tags":[],"class_list":["post-330","post","type-post","status-publish","format-standard","hentry","category-programming","category-software-development"],"_links":{"self":[{"href":"https:\/\/serverdude.dk\/index.php?rest_route=\/wp\/v2\/posts\/330","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/serverdude.dk\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/serverdude.dk\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/serverdude.dk\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/serverdude.dk\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=330"}],"version-history":[{"count":4,"href":"https:\/\/serverdude.dk\/index.php?rest_route=\/wp\/v2\/posts\/330\/revisions"}],"predecessor-version":[{"id":339,"href":"https:\/\/serverdude.dk\/index.php?rest_route=\/wp\/v2\/posts\/330\/revisions\/339"}],"wp:attachment":[{"href":"https:\/\/serverdude.dk\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=330"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/serverdude.dk\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=330"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/serverdude.dk\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=330"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}