jianghong

招聘软件工程师

In Uncategorized on June 29, 2010 at 5:30 am
本来想在离开美国前写篇文章告别加州和Google的,可是转眼已经回国一个多星期了。先发这篇招聘的帖子,有空再回顾过去吧。请各位帮忙推荐合适的人选。

Onyx International Inc.简介:

作为一家年轻的公司,我们创造了一流的电子阅读平台,软件产品,以及手持设备。我们的品牌也在国内外市场,特别是欧洲市场获得了一定的知名度。在拓展公司业务领域的过程中,我们希望更多的人才能加入我们,创造出下一个杀手级产品。我们的软件项目包括开发手持设备上的系统和应用程序软件,相关的互联网服务,以及内部工具。我们现有的工程师大都来自于世界一流的软件公司、高科技公司和高校。对我们来说,创新永远将是成功的关键。

我们有稳定赢利,并给予员工非常有竞争力的薪酬待遇。

公司涉足行业::

  • 电子消费类产品
  • 计算机软件
  • 互联网/电子商务

职位介绍

工作地点
广州/深圳 (我们现在广州,不过计划很快会在深圳也建立研发的部门)
月薪范围
有一定工作经验:1万-3万人民币(由面试结果和经验决定)
应届毕业生:根据面试结果商议
其他
公司为技术职位的员工报销ACM和IEEE的基本会员费。
所有职位的共同要求:
  • 热爱技术,乐于学习新知识。
  • 有Linux平台开发经验,能熟练使用Linux下的各种工具。
  • 熟悉包括版本控制工具,bug tracker在内的各种项目管理工具。
  • 工程师职位要求牢固掌握数据结构,算法等计算机科学的基础知识。
  • 有领导气质,敢于接受挑战,并善于与团队成员合作。
C++研发工程师/软件工程师
  • 熟练掌握C++语言。
  • 熟悉面向对象程序设计。
  • 有Qt或嵌入式开发经验者优先。
Java研发工程师/软件工程师
  • 熟练掌握Java语言。
  • 熟悉面向对象程序设计。
  • 有Android或嵌入式开发经验者优先。
网络服务研发工程师/软件工程师
  • 熟练掌握至少两门主流程序设计语言。
  • 有函数式语言(functional languages)或Lisp/Clojure等语言开发经验者优先。
  • 有服务器或web开发经验者优先。
UI设计师
没有特别的要求,我们判断的依据主要是以前的UI设计作品。职责包括设计手持设备上的用户界面以及web用户界面。

简历请发至 hjiang@onyx-international.com 。

本文由脚本自动转载自http://blog.hjiang.net

Nonintrusive concurrency with Clojure

In Uncategorized on December 12, 2009 at 1:49 am
最近对Clojure比较感兴趣,写了一个quick sort做测试。

单线程版:

(defn qsort-seq [seq]
  (if (<= (.length seq) 25)
    (selection-sort seq)
    (let [[first-half second-half] (qsort-partition seq 0)
          sorted-first-half (qsort-seq first-half)
          sorted-second-half (qsort-seq second-half)]
          (concat sorted-first-half sorted-second-half))))
多线程版:

(defn qsort [seq]
  (if (<= (.length seq) 25)
    (selection-sort seq)
    (let [[first-half second-half] (qsort-partition seq 0)
      sorted-first-half (future (qsort first-half))
      sorted-second-half (qsort second-half)]
      (concat @sorted-first-half sorted-second-half))))
可以看到两个版本基本是一样的,所以在Clojure里通常可以很快把单线程的程序并行化。下面是一些调用到的函数:

(def random (new java.util.Random))

(defn gen_rand_ints [n]
  (loop [result [], i n]
    (if (zero? i)
      result
      (recur (conj result (.nextInt random)) (dec i)))))

(def values (vec (gen_rand_ints 10000)))

(defn swap [vec i j]
  (let [iv (vec i),
    jv (vec j)]
    (assoc vec i jv j iv)))

(defn selection-sort [seq]
  (defn index_of_smaller [seq i j]
    (if (< (seq i) (seq j)) i j))
  (loop [seq- seq start 0]
    (if (< start (.length seq))
      (let [index_of_smallest_v
            (reduce (partial index_of_smaller seq-)
                    (range start (.length seq-)))
            new_seq (swap seq- start index_of_smallest_v)]
        (recur new_seq (inc start)))
      seq-)))

(defn qsort-partition [seq pivot_index]
  (let [pivot (seq pivot_index)
    pair (loop [i 0, le [], gt []]
           (if (< i (.length seq))
         (if (<= (seq i) pivot)
           (let [le (cons (seq i) le)]
             (recur (inc i) le gt))
           (let [gt (cons (seq i) gt)]
             (recur (inc i) le gt)))
         [(vec le), (vec gt)]))]
    pair))
比较一下两个版本排列10000个数的时间:

(time (qsort-seq values))
(time (qsort values))
(shutdown-agents)
输出

"Elapsed time: 1532.536441 msecs"
"Elapsed time: 1121.529135 msecs"

本文由脚本自动转载自http://blog.hjiang.net

C++ Pragmatics: Testing (Part 2, Mechanics)

In Uncategorized on November 5, 2009 at 1:43 am
Jelly fish

There are many tools for testing, and there are different kinds of testing at different granularities, for different phases of the development cycle.

For tests of the largest granularity, such as acceptance tests, the tools and methods are usually language neutral. For example, you can test a Ruby web application using webrat or watir, and you can use the same set of tools to test a C++ web server. In this section, I’m just going to focus on small tests, in particular, tests of individual methods and classes.

There are a number of test frameworks for C++. Boost has a test library, Qt has a unit test library, and Google also open-sourced its C++ testing framework. There are a few others. You could write tests without any of them, but the tools help to reduce repetition and make tests more concise. In my experience this is quite important, because the easier it is to write tests, the more motivated I am to write them.

The testing frameworks all use similar terminology. Usually a test source file contains one or more test cases, and a test case contains one or more tests. It’s customary to write one test case for each class, and one or more tests for each public method. Most of those tools are similar, and it doesn’t really matter which one you use. I like Google’s framework because it’s the least verbose and it’s also what I use at work. Here’s a quick example of one test in a test case for an RSS feed parser:

class FeedParserTest: public ::testing::Test {
  protected:
    void SetUp() {
        feed_.reset(new Feed);
    }

    RssFeedParser parser_;
    shared_ptr<Feed> feed_;
};

TEST_F(FeedParserTest, ParseSlashdot) {
    QFile rss(TEST_DATA_DIR "/slashdot.rss");
    ASSERT_TRUE(rss.exists());
    rss.open(QIODevice::ReadOnly);
    parser_.startNewFeed(feed_);
    while (rss.bytesAvailable() > 0) {
        parser_.append(rss.read(CHUNK_SIZE));
    }
    EXPECT_TRUE(parser_.finished());
    EXPECT_EQ("Slashdot", parser_.feed()->title());
    EXPECT_EQ("http://slashdot.org/", parser_.feed()->site_url());
}
Each test class inherit from testing::Test, and there are two virtual functions you could override to set up and tear down your test fixture. void SetUp() and void TearDown() are called before and after each test respectively. You can also define two static class functions static void SetUpTestCase() and static void TearDown() which are called before and after all tests in the test case respectively. In other words, they are only called once for the test case. Ideally, you should implement the test fixture in SetUp() and TearDown(), because you don’t want to introduce dependencies between the tests. For example, you don’t want to be in a situation where just rearranging the order of tests would break them. SetUpTestCase() and TearDownTestCase() are mainly used for expensive initialization such as reading large amounts of data from disk, which you don’t want to do for every single test.

The TEST_F() macro defines a test with fixture, which has access to the test class defined earlier. There is also a TEST() macro that defines a test without fixture which is essentially just a simple function. The framework provides two families of assertions that you can use in tests. The ASSERT_* family of assertions immediately abort the current test if the expected condition is not true. They are usually used when it doesn’t make sense to continue the test, for example, where there is a NULL pointer that you need to dereference later, or some critical data is missing. The EXPECT_* family of assertions cause the test fail if the condition does not hold, but they allow the test to continue, so that you can find all failing expectations in one run.

There is no need to write a main() function. The testing framework provides a standard main() that you can link with, which runs all all defined tests. The resulting test executable has a few command line options that you can use to filter tests or change output formats. Just run your test executable with the --help flag to see all available options.

(To be continued …)

本文由脚本自动转载自http://blog.hjiang.net

Follow

Get every new post delivered to your Inbox.