simonrenoult / code-complexity Goto Github PK
View Code? Open in Web Editor NEWMeasure the churn/complexity ratio. Higher values mean hotspots where refactorings should happen.
License: MIT License
Measure the churn/complexity ratio. Higher values mean hotspots where refactorings should happen.
License: MIT License
We're currently measuring complexity based on sloc
. It's nice but a long file doesn't always mean it's complex.
We could add a --complexity-strategy=<sloc or cyclomatic or xyz>
that would be used in the complexity processing.
Since churn is multiplied by complexity, shouldn't the result be the product of churn and complexity? If we were dividing churn by complexity, the result would be the ratio of churn to complexity.
Let me know if I'm missing something. Otherwise I'm happy to create a PR. :)
Hello, how're you? Thanks for such a great project first of all! 😄
I have a question, it seems like the glob I'm passing as a parameter isn't working, I have a bunch of yaml
files (.yml
and .yaml
extensions), and I need to filter them out
, I'm trying the next command as input:
$ code-complexity . --limit 5 --filter '*.yml,*.yaml'
I've also tried:
$ code-complexity . --limit 5 --filter '*.yml'
And I'm always getting an empty result:
┌──────┬────────────┬───────┬───────┐
│ file │ complexity │ churn │ score │
└──────┴────────────┴───────┴───────┘
What am I missing here? I've also tried
$ code-complexity . --limit 5 --filter '**/*.yaml'
But no luck 😢
Thanks in advance! 😄
Not really a feature but we depend on node-sloc
to count file complexity. Which is far from being popular and is at risk of being abandoned one day.
We should look into alternatives.
README file shows this as an example for applying multiple filters:
$ code-complexity <dir> --filter 'src/**','!src/front'
This doesn't seem to actually work. I think it should be $ code-complexity <dir> --filter 'src/**, !src/front'
instead as that seems to work.
Apologies for creating an issue, I couldn't find any contact details. Thanks for writing this tool,I was wondering if it can give accurate results for Sass/SCSS files? How is the complexity calculated in a language agnostic manner?
Thanks
I get this message BTW: warning: inexact rename detection was skipped due to too many files. warning: you may want to set your diff.renameLimit variable to at least 755 and retry the command.
in a kotlin project, the complexity is 1 in every file
Cohesion is a core element of software quality. It defines the degree to which the elements of a module belong together (source). Measuring cohesion means measuring how strong relationships between modules are.
Cohesive piece of code should move and change together. On the contrary, when two unrelated pieces of code move together, it reveals a strong relationship between them, which reveals design weaknesses.
Since cohesive pieces of code move together, they are likely to be changed within the same commit.
Cohesive pieces of code are located close to each other.
If they are not, we can argue that cohesiveness weakens.
Furthermore, if a commit contains unrelated pieces of code, then we could argue that cohesiveness also weakens.
Since v4.0.0, if one wants to integrate code-complexity
with another program, the recommended solution is to use the json
flag, example:
const { execSync } = require("fs");
const raw = execSync("npx code-complexity ../foo/bar --format=json");
const result = JSON.parse(raw);
Which is not ideal since it feels a bit hacky and the datastructure is unknown from a user point of view.
A cool way to do things would be to be able to import code-complexity
as a dependency, example:
const codeComplexity = require('code-complexity');
const options = { directory: '../foo/bar' };
const result = await codeComplexity.compute(options);
I initially planned that feature for v4.0.0
but struggled with the TypeScript module system. Help definitely wanted :)
Hi, I came across this package when reading a blog. Please let know if I'm missing something, but when I cloned the repo and attempted to install the dependencies I came across two errors.
Environment
Node v18.12.1
Using WSL on windows 11
Steps to reproduce
Actual result
> [email protected] prepare
> npm run lint && npm run build
> [email protected] lint
> eslint --ext .ts .
> [email protected] build
> rm -rf dist && tsc
src/io/output.ts:2:28 - error TS2307: Cannot find module '../../dist/src/lib/statistics' or its corresponding type declarations.
2 import { IStatistic } from "../../dist/src/lib/statistics";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
src/lib/statistics/statistics.ts:1:28 - error TS2307: Cannot find module '../../../dist/src/lib/statistics' or its corresponding type declarations.
1 import { IStatistic } from "../../../dist/src/lib/statistics";
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Found 2 errors in 2 files.
Errors Files
1 src/io/output.ts:2
1 src/lib/statistics/statistics.ts:1
Expected result
To return to prompt without errors with the project build (in the dist folder)
Attempts to solve the issue
If I change the imports to IStatistic
in /src/lib/statistic.ts - I'm able to build and subsequently run tests.
Am I missing something ?
Questions
Does this have something to do with how to use the tool via npx
if we haven't installed the package locally as to why the imports for IStatistic
point to the dist folder ?
After thoughts
Again I realise I'm coming at this fresh but this brought up some other thoughts.
ts-node
for the project.I'd be happy to open a PR to add those additional scripts if you think it would be of benefit.
I wanted to try this tool and it just bombes brakes when I try to collect the complexity.
./node_modules/.bin/code-complexity . --details
(node:11696) UnhandledPromiseRejectionWarning: Error: stdout maxBuffer exceeded
at Socket.onChildStdout (child_process.js:329:14)
at emitOne (events.js:116:13)
at Socket.emit (events.js:211:7)
at addChunk (_stream_readable.js:263:12)
at readableAddChunk (_stream_readable.js:246:13)
at Socket.Readable.push (_stream_readable.js:208:10)
at Pipe.onread (net.js:601:20)
(node:11696) UnhandledPromiseRejectionWarning: Unhandled promise rejection. This error originated either by throwing inside of an async function without a catch block, or by rejecting a promise which was not handled with .catch(). (rejection id: 1)
(node:11696) [DEP0018] DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code.
What works it the following
./node_modules/.bin/code-complexity --help
Usage: code-complexity <dir>
Measure projects complexity based on files sloc and commit count.
Options:
-l, --limit [limit] Limit the number of files to output
-d, --details Show the number of commit and computed sloc
-c, --commit Show the number of commits
-s, --sloc Show the computed sloc
-i, --since [since] Limit the age of the commit analyzed
-n, --no-first-parent Do not use the git-log flag '--first-parent' when counting commits
--sort [sort] Sort results by commit, complexity, file or sloc
--min [min] Exclude results below <min>
--max [max] Exclude results above <max>
-h, --help output usage information
Examples:
$ code-complexity /path/to/git/directory
$ code-complexity /path/to/git/directory --limit 3
$ code-complexity /path/to/git/directory --details
$ code-complexity /path/to/git/directory --min 10 --max 50
node -v // => v8.12.0
npm -v // => 6.4.1
uname -a // => Linux agirorn 4.15.0-38-generic #41-Ubuntu SMP Wed Oct 10 10:59:38 UTC 2018 x86_64 x86_64 x86_64 GNU/Linux
In WSL it works like a charm, but in Windows I get the Error: Program 'git' must be installed
error, because 'which' is not recognized as an internal or external command
😞
I tried using Set-Alias which where.exe
and it works on the command line:
PS C:\windows\system32> which git
C:\Program Files\Git\cmd\git.exe
But I still get
'which' is not recognized as an internal or external command,
operable program or batch file.
Error: Program 'git' must be installed
😞
I get the above output with my repo. How can I fix that?
I noticed when running the CLI --> When format is json test, that a dep warning in future versions of Node fs.rmdir will be removed and recommended using fs.rm instead.
I see in the fixtures file we use rmdirSync
method, its quite a small thing really, but to remove the dep info using the rmSync method instead might be worth considering.
I get a table printed when I add the flag --format csv
.
Same output as I would get without flags or --format table
I'm running this on Windows 10, both CMD and Powershell - looks like there is a dependency on something I don't have.
Error: Command failed: git -C ./ log --follow --format='' --name-only '*' | sort | uniq -c 'uniq' is not recognized as an internal or external command, operable program or batch file. fatal: invalid --pretty format: ''
Node version: latest but tried in some earlier ones.
npx code-complexity . --since 6.month --limit 8 --sort score
node:internal/modules/cjs/loader:936
throw err;
^
Error: Cannot find module 'esprima'
Require stack:
- /Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/escomplex/src/index.js
- /Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/code-complexity/dist/src/lib/complexity/strategies/cyclomatic.js
- /Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/code-complexity/dist/src/lib/complexity/complexity.js
- /Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/code-complexity/dist/src/lib/complexity/complexities.js
- /Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/code-complexity/dist/src/lib/statistics/statistics.js
- /Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/code-complexity/dist/src/lib/index.js
- /Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/code-complexity/dist/src/io/index.js
- /Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/code-complexity/dist/bin/code-complexity.js
at Function.Module._resolveFilename (node:internal/modules/cjs/loader:933:15)
at Function.Module._load (node:internal/modules/cjs/loader:778:27)
at Module.require (node:internal/modules/cjs/loader:1005:19)
at require (node:internal/modules/cjs/helpers:102:18)
at Object.<anonymous> (/Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/escomplex/src/index.js:5:15)
at Module._compile (node:internal/modules/cjs/loader:1101:14)
at Object.Module._extensions..js (node:internal/modules/cjs/loader:1153:10)
at Module.load (node:internal/modules/cjs/loader:981:32)
at Function.Module._load (node:internal/modules/cjs/loader:822:12)
at Module.require (node:internal/modules/cjs/loader:1005:19) {
code: 'MODULE_NOT_FOUND',
requireStack: [
'/Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/escomplex/src/index.js',
'/Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/code-complexity/dist/src/lib/complexity/strategies/cyclomatic.js',
'/Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/code-complexity/dist/src/lib/complexity/complexity.js',
'/Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/code-complexity/dist/src/lib/complexity/complexities.js',
'/Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/code-complexity/dist/src/lib/statistics/statistics.js',
'/Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/code-complexity/dist/src/lib/index.js',
'/Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/code-complexity/dist/src/io/index.js',
'/Users/lsoares/.npm/_npx/4efef98b5952fb36/node_modules/code-complexity/dist/bin/code-complexity.js'
]
}
Since code-complexity
is mostly used as a static analysis tool, it would be nice to be able to analyze any project, without having to pull it locally.
Currently, the only required argument is the directory to analyze. We could also support a URL.
Support URL in addition to path, example:
$ npx code-complexity https://github.com/simonrenoult/code-complexity.git
Internally, it could clone the project in /tmp
and remove it once the analysis is done.
When I run 4.0.0 using the example from the readme, npx
then it fails with
Error: Cannot find module 'esprima'
Installing with npm install code-complexity
also does not pull it in. Explicitly installing with npm install esprima
solves the issue.
I'm no nodejs expert, so I don't know how to present a fix for this -I'm not familiar with bundleDependencies
- but I suspect something in the package.json is off, or some vendored package should be included.
Running npx code-complexity . -cs halstead
returns the error Error: Cannot find module '@babel/plugin-transform-typescript'
Error
$ npx code-complexity . -cs halstead
Beware, the 'halstead' and 'cyclomatic' strategies are only available for JavaScript/TypeScript.
Error: Cannot find module '@babel/plugin-transform-typescript'
Require stack:
- /home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/files/plugins.js
- /home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/files/index.js
- /home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/index.js
- /home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/dist/src/lib/complexity/cyclomatic.js
- /home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/dist/src/lib/complexity/index.js
- /home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/dist/src/lib/statistics.js
- /home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/dist/src/lib/index.js
- /home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/dist/src/io/index.js
- /home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/dist/bin/code-complexity.js
at Module._resolveFilename (node:internal/modules/cjs/loader:939:15)
at resolve (node:internal/modules/cjs/helpers:108:19)
at tryRequireResolve (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/files/plugins.js:128:9)
at resolveStandardizedNameForRequire (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/files/plugins.js:162:19)
at sync (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/files/plugins.js:185:12)
at sync (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/gensync/index.js:182:19)
at /home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/gensync/index.js:210:24
at Generator.next (<anonymous>)
at resolvePlugin (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/files/plugins.js:60:17)
at resolvePlugin.next (<anonymous>)
at loadPlugin (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/files/plugins.js:66:27)
at loadPlugin.next (<anonymous>)
at createDescriptor (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/config-descriptors.js:148:16)
at createDescriptor.next (<anonymous>)
at evaluateSync (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/gensync/index.js:251:28)
at /home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/gensync/index.js:31:34
at Array.map (<anonymous>)
at Function.sync (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/gensync/index.js:31:22)
at Function.all (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/gensync/index.js:210:24)
at Generator.next (<anonymous>)
at createDescriptors (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/config-descriptors.js:109:41)
at createDescriptors.next (<anonymous>)
at createPluginDescriptors (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/config-descriptors.js:106:17)
at createPluginDescriptors.next (<anonymous>)
at /home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/config-descriptors.js:69:32
at Generator.next (<anonymous>)
at Function.<anonymous> (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/gensync-utils/async.js:21:3)
at Generator.next (<anonymous>)
at evaluateSync (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/gensync/index.js:251:28)
at Function.sync (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/gensync/index.js:89:14)
at sync (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/gensync-utils/async.js:66:25)
at sync (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/gensync/index.js:182:19)
at onFirstPause (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/gensync/index.js:210:24)
at Generator.next (<anonymous>)
at cachedFunction (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/caching.js:54:46)
at cachedFunction.next (<anonymous>)
at mergeChainOpts (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/config-chain.js:357:34)
at mergeChainOpts.next (<anonymous>)
at chainWalker (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/config-chain.js:324:14)
at chainWalker.next (<anonymous>)
at buildRootChain (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/config-chain.js:58:36)
at buildRootChain.next (<anonymous>)
at loadPrivatePartialConfig (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/partial.js:79:62)
at loadPrivatePartialConfig.next (<anonymous>)
at loadFullConfig (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/full.js:36:46)
at loadFullConfig.next (<anonymous>)
at transform (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/transform.js:20:45)
at transform.next (<anonymous>)
at evaluateSync (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/gensync/index.js:251:28)
at sync (/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/gensync/index.js:89:14) {
code: 'MODULE_NOT_FOUND',
requireStack: [
'/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/files/plugins.js',
'/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/config/files/index.js',
'/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/node_modules/@babel/core/lib/index.js',
'/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/dist/src/lib/complexity/cyclomatic.js',
'/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/dist/src/lib/complexity/index.js',
'/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/dist/src/lib/statistics.js',
'/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/dist/src/lib/index.js',
'/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/dist/src/io/index.js',
'/home/peter/.nvm/versions/node/v18.0.0/lib/node_modules/code-complexity/dist/bin/code-complexity.js'
]
}
Tested with
Os: Linux
I have no clue what is going wrong. /home/peter/.nvm/versions/node/v14.19.1/lib/node_modules/code-complexity/node_modules/@babel/plugin-transform-typescript
is installed.
Hi, I wondered whether a few updates to the readme might be useful.
A one line explanation of the different complexity metrics we can choose in the package (A rational for those metrics might be quite nice too) might make it slightly easier for those who don't know much about complexity metrics to understand the package.
Also just a small thing I noticed on the readme, there's no where it says what the default strategy for complexity is if we don't explicitly set it. Reading the code I noticed it was sloc
and I suspect you can guess this when you run it for the first time but wondered whether its worth being explicit about this?
It seems like the library expects the package.json
to be in the root dir. This is problematic if you want to use it on a larger codebase where submodules define their own package.json
. I'm on a mac but think the issue is platform agnostic.
mkdir test && cd test
git init
mkdir subfolder && cd subfolder
npm init -y
cd ..
npx code-complexity .
Output:
Error: Error: no package.json found, exiting.
at Object.<anonymous> (/Users/lcondrea/.npm/_npx/81792/lib/node_modules/code-complexity/dist/src/utils.js:83:31)
at step (/Users/lcondrea/.npm/_npx/81792/lib/node_modules/code-complexity/dist/src/utils.js:33:23)
at Object.next (/Users/lcondrea/.npm/_npx/81792/lib/node_modules/code-complexity/dist/src/utils.js:14:53)
at fulfilled (/Users/lcondrea/.npm/_npx/81792/lib/node_modules/code-complexity/dist/src/utils.js:5:58)
Try to execute from subfolder
cd subfolder
npx code-complexity .
Output:
npx: installed 64 in 4.345s
Error: Argument 'dir' must be the git root directory.
at assertIsGitRootDirectory (/Users/lcondrea/.npm/_npx/81797/lib/node_modules/code-complexity/dist/src/lib/churn.js:111:15)
at /Users/lcondrea/.npm/_npx/81797/lib/node_modules/code-complexity/dist/src/lib/churn.js:61:13
at step (/Users/lcondrea/.npm/_npx/81797/lib/node_modules/code-complexity/dist/src/lib/churn.js:33:23)
at Object.next (/Users/lcondrea/.npm/_npx/81797/lib/node_modules/code-complexity/dist/src/lib/churn.js:14:53)
at /Users/lcondrea/.npm/_npx/81797/lib/node_modules/code-complexity/dist/src/lib/churn.js:8:71
at new Promise (<anonymous>)
at __awaiter (/Users/lcondrea/.npm/_npx/81797/lib/node_modules/code-complexity/dist/src/lib/churn.js:4:12)
at compute (/Users/lcondrea/.npm/_npx/81797/lib/node_modules/code-complexity/dist/src/lib/churn.js:57:12)
at Object.withDuration (/Users/lcondrea/.npm/_npx/81797/lib/node_modules/code-complexity/dist/src/utils.js:63:21)
at Object.compute (/Users/lcondrea/.npm/_npx/81797/lib/node_modules/code-complexity/dist/src/lib/churn.js:53:24)
Hi,
I noticed when I did manage to install the dependencies that I got this about code-cov
npm WARN deprecated [email protected]: https://about.codecov.io/blog/codecov-uploader-deprecation-plan/
Looking at the website it looks like its been deprecated now but on a quick glance looks like its not something you install as a dependency. Is this dependency used now ? I looked back in the commit history and see that nyc is used for code coverage rather than codecov.
We're currently outputting either a table or a json. A cool way to visualize the complexity/churn ratio would be a graph of files. HTML + d3js or something like that should do the trick.
Adding a --format=html
flag to the cli that generates a public
directory containing a ready to open index.html
with the graph.
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.