Skip to content

Instantly share code, notes, and snippets.

@onlytiancai
Created February 4, 2012 15:04
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save onlytiancai/1738383 to your computer and use it in GitHub Desktop.
Save onlytiancai/1738383 to your computer and use it in GitHub Desktop.
对象健身操演练-grep
/*
## 对象健身操
http://www.infoq.com/cn/minibooks/thoughtworks-anthology
###规范
1. 方法只使用一级缩进。
1. 全部符合要求
1. 大部分通过方法提取做到,有的带yield的语句块不好提取,幸好一些Linq方法可以用来抽象一些集合操作。
1. 所有方法都尽量控制在5行以内,不包含空行和括号单独占的行
1. 拒绝使用else关键字。
1. 全部符合要求
1. 全部使用提前return来达到要求,没有使用多态和表驱动
1. 封装所有的原声类型和字符串。
1. 没有符合要求
1. 这么细粒度的封装,感觉有些蛋疼,没有刻意去满足要求
1. 一行代码只有一个‘.'运算符。
1. 基本符合要求
1. 有一些含lambda表达式的语句一行有两个.,个人感觉不影响美观
1. 不用使用缩写。
1. 全部符合要求
1. dir不需要写成Directory吧,一些约定俗成的缩写还是别展开好,否则显得罗嗦
1. 保持实体对象简单清晰。
1. 全部符合要求
1. 所有类不超过50行,不包括using语句,空白语句和括号单独占的行
1. 任何类中的实例变量都不要超过2个。
1. 全部符合要求
1. 可能这个例子比较简单,所以做到了
1. 使用一流的集合。
1. 全部符合要求
1. 所有集合用.NET类库自带的
1. 不使用任何Getter/Setter/Property。
1. 全部符合要求
1. 所有实例属性没有对外暴露,只暴露了方法
### 修改记录
1. 2012.02.05:只输出匹配结果的文件,并在结果行上附加上文件路径信息
*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.IO;
using System.Threading.Tasks;
using System.Text.RegularExpressions;
namespace Wawasoft.LinuxTools
{
class Program
{
static void Main(string[] args)
{
if (!IsArgsOk(args))
{
return;
}
string searchPattern = args[0];
string filePattern = args[1];
Console.WriteLine("searchPattern:{0} filePattern:{1}", searchPattern, filePattern);
Grep grep = new Grep(searchPattern, filePattern);
grep.Run();
}
static bool IsArgsOk(string[] args)
{
if (args.Length != 2)
{
Console.WriteLine("Usage: grep <searchPattern> <filePattern>");
Console.WriteLine(@"Example: grep \d+ d:\code\*.py");
return false;
}
return true;
}
}
public class Grep
{
private IEnumerable<FileInfo> _files = null;
private string _searchPattern = null;
public Grep(string searchPattern, string filePattern)
{
_files = FileFilter.GetFiles(filePattern);
_searchPattern = searchPattern;
}
public void Run()
{
Parallel.ForEach(_files, (file) =>
{
OneFileGrep grep = new OneFileGrep(file, _searchPattern);
PrintResult(file, grep.GetResult());
});
}
private void PrintResult(FileInfo file, IEnumerable<string> result)
{
foreach (string line in result)
{
Console.WriteLine(line);
}
}
}
public class FileFilter
{
public static IEnumerable<FileInfo> GetFiles(string filePattern)
{
string pattern = FilePattern.GetPattern(filePattern);
DirectoryInfo currentDir = FilePattern.GetDir(filePattern);
return GetFilesFromCurrentDir(currentDir, pattern);
}
private static IEnumerable<FileInfo> GetFilesFromCurrentDir(DirectoryInfo currentDir, string filePatten)
{
IEnumerable<FileInfo> currentDirFiles = currentDir.GetFiles(filePatten);
IEnumerable<FileInfo> subDirFiles = GetFilesFromSubDir(currentDir, filePatten);
return UnionFiles(currentDirFiles, subDirFiles);
}
private static IEnumerable<FileInfo> GetFilesFromSubDir(DirectoryInfo currentDir, string filePatten)
{
DirectoryInfo[] subDirs = currentDir.GetDirectories();
IEnumerable<FileInfo> allSubDirFiles = null;
foreach (DirectoryInfo subDir in subDirs) //这里不能用Parallel.ForEach,因为IEnumerable.Union是延迟执行的
{
allSubDirFiles = UnionFilesByDir(allSubDirFiles, subDir, filePatten);
}
return allSubDirFiles;
}
private static IEnumerable<FileInfo> UnionFilesByDir(IEnumerable<FileInfo> allSubDirFiles, DirectoryInfo dir, string filePatten)
{
IEnumerable<FileInfo> subDirFiles = GetFilesFromCurrentDir(dir, filePatten);
return UnionFiles(allSubDirFiles, subDirFiles);
}
private static IEnumerable<FileInfo> UnionFiles(IEnumerable<FileInfo> allSubDirFiles, IEnumerable<FileInfo> subDirFiles)
{
if (subDirFiles == null)
return allSubDirFiles;
if (allSubDirFiles == null)
return subDirFiles;
return allSubDirFiles.Union(subDirFiles);
}
}
public class FilePattern
{
public static DirectoryInfo GetDir(string filePattern)
{
string dirName = Path.GetDirectoryName(filePattern);
if (string.IsNullOrEmpty(dirName))
{
string strCurrentDir = Directory.GetCurrentDirectory();
return new DirectoryInfo(strCurrentDir);
}
return new DirectoryInfo(dirName);
}
public static string GetPattern(string filePattern)
{
return Path.GetFileName(filePattern);
}
}
class OneFileGrep
{
private FileInfo _file;
private Regex _searchPattern = null;
public OneFileGrep(FileInfo file, string searchPattern)
{
this._file = file;
this._searchPattern = new Regex(searchPattern, RegexOptions.IgnoreCase);
}
public IEnumerable<string> GetResult()
{
StreamReader reader = new StreamReader(_file.FullName);
return GetResult(reader);
}
private IEnumerable<string> GetResult(StreamReader reader)
{
IEnumerable<LineInfo> lines = GetLines(reader);
var matchLines = lines.Where((line, i) => _searchPattern.IsMatch(line.Text));
foreach (LineInfo line in matchLines)
{
yield return string.Format("{0}({1}):{2}",_file.FullName, line.LineNo, line.Text);
}
}
private IEnumerable<LineInfo> GetLines(StreamReader reader)
{
string line = reader.ReadLine();
int lineNo = 1;
while (line != null)
{
yield return new LineInfo { LineNo = lineNo, Text = line };
line = reader.ReadLine();
lineNo = lineNo + 1;
}
reader.Close();
}
class LineInfo
{
public int LineNo { get; set; }
public string Text { get; set; }
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment