[转载]百度地图API详解之移动平台开发的最佳实践

mikel阅读(1309)

[转载]百度地图API详解之移动平台开发的最佳实践 – jz1108 – 博客园.

百度地图API详解

这是百度地图API详解系列文章的第二篇,主要介绍如何在iPhone和Android平台上使地图API进行开发(这里指的是在浏览器端执行的JavaScript版本API)。

大部分情况下,在iPhone和Android上开发与PC上开发没有两样,开发者调用API的代码都是一样的,这里主要介绍如何针对移动设备的特点更好的开发地图应用,以及介绍一些与移动平台相关的API。

建议移动平台的开发者仔细阅读一遍Safari Web Content GuideWeb Applications系列文章, 他们会告诉你移动Web开发的基本知识。

构建页面

下面我们开始构建移动平台的地图。首先我们声明文档类型为HTML5:

<!DOCTYPE html>

目前iPhone和Android平台的浏览器都能较好的支持HTML5标准,因此建议移动页面都声明为HTML5文档类型。

接着调整页面的显示比例,在html页面中增加下面的meta标签:

<metaname="viewport"content="initial-scale=1.0, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no"/>

这里将页面的显示比例调整为1:1,并且禁止用户通过双指缩放页面。其中minimum-scale和maximum-scale用来防止在设备旋转时页面发生缩放。下面我们添加地图容器:

<div id="container"></div>

和样式:

html{height:100%}
body{height:100%;margin:0px;padding:0px}
#container{height:100%}

注意到我们给地图容器指定了100%的宽和高,这样做一方面是让地图区域尽可能 大,方便用户操作;另一方面是因为目前移动版的浏览器的API还不完善,如果地图没有充满屏幕会导致bug(主要是手指操作时位置会出现偏差,如果你的地 图展示不需要移动、缩放,那么不充满屏幕也没有影响)。

接下来我们初始化地图,其实代码和PC上没有差别:

var map = new BMap.Map("container"); // 创建Map实例
var point = new BMap.Point(116.404, 39.915); // 创建点坐标
map.centerAndZoom(point,15); // 初始化地图,设置中心点坐标和地图级别。

你将在iPhone(iPhone3截图)中看到如下效果,即使设备旋转地图也能正常显示:


高解析度

众所周知,iPhone4和iPhone3相比,在同样物理尺寸的情况下,宽度和高度分辨率各扩大了一倍,你会发现同样的地图在iPhone3和iPhone4上显示效果是不同的。下面是iPhone4的屏幕截图(此图为实际尺寸的50%):

你会发现地图图片有点儿发虚。这是因为iPhone4的屏幕分辨率为960×640,而你的页面尺寸仍旧在480×320模式下,就是说地图图片被拉伸了。为了在iPhone4这样的高分辨率设备上更清晰的展示地图,在创建地图对象时可以通过配置参数开启高解析度模式:

var map = new BMap.Map("container", {enableHighResolution: true})

这时再来看iPhone4的效果(这回我们以960×640的实际尺寸展示):

注意,即使你开启了高解析度模式,在iPhone3等普通屏幕上还是按照原先的样式显示,也就是说只有真正的高分辨率设备才能使用此模式。

在Android平台上,手机种类、型号更为丰富,因此不同的手机的分辨率、物理尺寸都不同,我们可统一使用dpi来衡量,高dpi的手机也可以开启高解析度地图模式。下面是同一设备开启高解析度前后的对比效果(为实际尺寸的50%):

在高解析度模式下,你所使用的元素(包括HTML元素、图片等)都应该在宽度和高 度上都应该进行扩大,在iPhone4上应各扩大一倍,在Android上应各扩大为原来的1.5倍。否则元素在浏览器中会显得比较小,不论从视觉上还是 操作上都影响用户体验。比如你设置的标注图标大小为23×26,那么在iPhone4的高解析度模式下你的图标尺寸应扩大到46×52。怎么知道地图在用 户的设备上是否真正处于高解析度模式呢?很简单,通过map的highResolutionEnabled方法即可判断。当且仅当你开启了高解析度模式并 且设备确实支持的时候此方法返回true。需要注意的是,在高解析度模式模式下地图图块数量会增加,用户访问的速度以及流量都会受到一些影响。
用户操作

惯性拖拽是个很酷的效果,当用户手指在移动地图后从设备表面抬起的时候,地图还会 根据用户刚才手指的移动方向和力度再移动一小段距离。仿佛整个地图图层具有惯性效果。这个功能通过调用map的 enableInertialDragging方法即可开启。在iPhone上,用户可通过双指对地图进行缩放和移动,你也可以通过map的 enablePinchToZoom来确定是否开启该功能(默认开启)。而在Android平台上,由于目前还没有开放双指操作相关的API,因此建议在 此平台上的地图中增加两个按钮用来控制地图的放大和缩小,同时也需要考虑高解析度模式按钮尺寸的问题。

[转载]Android开发者指南(13) —— With AVD Manager

mikel阅读(899)

[转载]Android开发者指南(13) —— With AVD Manager – 农民伯伯 – 博客园.

前言

本章内容为开发者指南(Dev Guide)/Developing/Managing Virtual Devices/With AVD Manager,版本为Android3.1 r1,翻译来自:”MeetAndroid”,欢迎大家访问他的博客:”http://blog.csdn.net/meetandroid“,再次感谢”MeetAndroid” !期待你一起参与翻译Android的相关资料,联系我over140@gmail.com。

声明

欢迎转载,但请保留文章原始出处:)

博客园:http://www.cnblogs.com/

Android中文翻译组:http://goo.gl/6vJQl

原文

http://developer.android.com/guide/developing/devices/managing-avds.html

AVD管理器来管理AVD

AVD管理器来管理AVDAndroid虚拟设备)配置很容易。一个AVD就是一份Android仿真器的设备配置,仿真器可以模拟Android所支持设备的不同配置。通过Eclipse或命令行的android工具起动AVD管理器后,就会看到它了。如图1所示:

1. AVD管理器屏幕截图。

通过主屏幕,可以创建,删除,更改和启动AVD。还可以查看AVD的详情。

创建AVD (Creating an AVD)

你可以根据自己的需要,创建任意数量的AVD。推荐的做法是,在高于目标API级的所有API级上测试自己的应用程序。

创建AVD步骤:

1. 起动AVD管理器:

* Eclipse中:选择Window > Android SDK and AVD Manager,或点击Eclipse工具栏中的Android SDK and AVD Manager图标。

* 在其它IDE中:到SDKtools/目录中,执行android工具,不用给任何参数。

2. Virtual Devices面板中,可以看到已创建的AVD的列表。点击New可以创建一个新的AVD,这时会显示Create New AVD对话框。

2. 创建AVD的窗口屏幕截图

3. 填写AVD详情。

需要给出名称、目标平台、SD卡大小和皮肤(默认为HVGA)。此外,还可以通过点击New…按钮并选择相应功能来添加特殊的硬件功能。要获取硬件功能的清单,请查阅硬件选项

注:确保按照应用程序的构建目标(AVD平台目标的API级必须等于或高于应用程序编译的API级)来为AVD定义目标设备。

4. 点击Create AVD

现在,AVD就准备好了。接下来可以关闭SDKAVD管理器、或创建更多的AVD。也可以选择一个设备的AVD,并点击Start来启动仿真器。

硬件选项(ardware options)

新创建AVD时,可指定下列用于模拟的硬件选项:

特征

描述

属性

设备内存尺寸

设备的物理内存数量,以兆字节计,默认值为“6”。

hw.ramSize

触摸屏支持

设备是否有一个触摸屏,默认值为“yes”。

hw.touchScreen

轨迹球支持

设备是否有一个轨迹球,默认值为“yes”。

hw.trackBall

键盘支持

设备是否有一个QWERTY键盘,默认值为“yes”。

hw.keyboard

拨号盘支持

设备是否有拨号盘按键,默认值为“yes”。

hw.dPad

GSM modem支持

设备是否有SDM modem,默认值为“yes”。

hw.gsmModem

摄像头支持

设备是否有摄像头,默认值为“no”。

hw.camera

摄像头水平最大像素

默认值为“640”。

hw.camera.maxHorizontalPixels

摄像头垂直最大像素

默认值为“480”。

hw.camera.maxVerticalPixels

GPS支持

设备是否有GPS,默认值为“yes”。

hw.gps

电池支持

设备是否有电池,默认值为“yes”。

hw.battery

加速度感应器

设备是否有加速度感应器,默认值为“yes”。

hw.accelerometer

音频录制支持

设备是否能录制音频,默认值为“yes”。

hw.audioInput

音频回放支持

设备是否能回放音频,默认值为“yes”。

hw.audioOutput

SD卡支持

设备是否支持虚拟SD卡的插入/拔出,默认值为“yes”。

hw.sdCard

缓存分区支持

设备是否使用/cache分区,默认值为“yes”。

disk.cachePartition

缓存分区大小

默认值为“66MB”。

disk.cachePartition.size

LCD密度

设备AVD屏幕的密度特征,默认值为”160”。

hw.lcd.density

轨迹球支持

是否有轨迹球。

hw.trackBall

补充

文章精选

创建 Android虚拟设备 AVD

[转载]Asp.net mvc 网站之速度优化 -- Memcached

mikel阅读(1079)

[转载]Asp.net mvc 网站之速度优化 — Memcache – enjoyeclipse – 博客园.

前一章说了一下使用页面缓存的问题,这次说一下数据缓存,我们使用的是Memcache作为数据缓存。

下面弱弱地引用一下百度百科关于Memcache的定义:

Memcache是一个高性能的分布式的内存对象缓存系统,通过在内存里维护一个统一的巨大的hash表,它能够用来存储各种格式的数据,包括图像视频文件以及数据库检索的结果等。Memcache是danga的一个项目,最早是LiveJournal 服务的,最初为了加速 LiveJournal 访问速度而开发的,后来被很多大型的网站采用。

1.Memcache服务器端的安装与启动

  1. 下载memcache,我们使用的版本是1.2.5。
  2. 使用命令行方式安装memcached-1.2.5.exe:  memcached-1.2.5.exe -d install
  3. 启动memcached: memcached-1.2.5.exe -d start
  4. 确认Windows 服务中memcached服务已经安装成功:
  5. 需要注意的是memcached服务是使用的11211端口,如果开启了防火墙,需要将11211添加到例外中。



2.网站中配置BeITMemcached

  1. 下载BeITMemcached_source_2010_08_04.zip, 并编译出BeITMemcached的DLL文件添加到项目的解决方案中:
  2. 配置Web.Config

<!– 第三方的组件配置–>

<configSections>

<section name=”beitmemcached” type=”System.Configuration.NameValueSectionHandler” />

</configSections>

<beitmemcached>

<add key=”MemcachedConfig” value=”localhost” />

</beitmemcached>

我们目前的访问量还不是很大,因此将Memcached与网站部署在一台机器上,使用的是localhost.  如果网站和Memcache部署在不同机  器,这里的value 就应该是memcached所在机器的IP,请再次确认11211端口可以访问。

3. Memcache在业务代码中的设计

前面把配置都弄完了,现在需要说一下Memcache在业务代码中的设计了。我们使用的是Controller->Service->Model的模式,切入点就在Service层。

首先构造一个接口ICachePolicy:

 public interface ICachePolicy    {
  
  void Add<T>(string key, T value);
  
  void Add<T>(string key, T value, DateTime dt);
  
  T Get<T>(string key);
  
  void Add(string key, object value);
 
 void Add(string key, object value, DateTime dt);
 
 object Get(string key);
 
 void Delete(string key);
 
 }

接着实现MemcachedCachePolicy实现ICachePlolicy:

public class MemcachedCachePolicy : ICachePolicy
 {
        private static readonly ILog Logger = LogManager.GetCurrentClassLogger();
 
         private readonly MemcachedClient _cache;
 
         public MemcachedCachePolicy()
         {
             _cache = MemcachedClient.GetInstance("MemcachedConfig");
             
             _cache.MaxPoolSize = 10000;
         }
 
         public void Add<T>(string key, T value)
         {
             if (_cache.Set(key, value))
             {
                 Logger.Debug("Set _cache for key successed, key[" + key + "]");
             }
             else
             {
                 Logger.Debug("Set _cache for key failed");
             }
         }
 
         public void Add<T>(string key, T value, DateTime dt)
         {
             _cache.Set(key, value, dt);
         }
 
         public T Get<T>(string key)
         {
             try
             {
                 return (T)_cache.Get(key);
             }
             catch (Exception e)
             {
                 Logger.Debug("Get _cache for key failed, key[" + key + "]", e);
                 _cache.Delete(key);
                 return default(T);
             }
         }
 
         public void Add(string key, object value)
         {
             _cache.Set(key, value);
         }
 
         public void Add(string key, object value, DateTime dt)
         {
             _cache.Set(key, value, dt);
         }
 
         public object Get(string key)
         {
             return _cache.Get(key);
         }
 
         public void Delete(string key)
         {
             _cache.Delete(key);
         }
     }

最后构造一个BaseCacheService,让BussinessService都继承BaseCacheService, 比如什么ProductService, ShopService等等。对外可见的是BaseCacheService, 而MemcachePolicy对于其他代码来说就是透明的了。

 public abstract class BaseCacheService
     {
         protected readonly ICachePolicy _cachePolicy;
 
         protected BaseCacheService()
         {
 
         }
 
         protected BaseCacheService(ICachePolicy cachePolicy)
         {
             _cachePolicy = cachePolicy;
         }
         
         protected T GetCache<T>(string key) where T: class
         {
             return _cachePolicy.Get<T>(key);
         }
 
         protected void Add<T>(string key, T items)
         {
             _cachePolicy.Add(key, items);
         }
 
         protected T GetOrAdd<T>(string key, T loadedItems) where T : class
         {
             var items = _cachePolicy.Get<T>(key);
            
             if (items == null)
             {
                 _cachePolicy.Add(key, loadedItems);
                 return loadedItems;
             }
 
             return items;
         }
 
         protected T GetOrAdd<T>(string key, Func<T> howToGet) where T : class
         {
             var items = _cachePolicy.Get<T>(key);
 
             
             if (items == null)
             {
                 var loadedItems = howToGet();
                 _cachePolicy.Add(key, loadedItems);
                 return loadedItems;
             }
 
             var type = items.GetType();
             if (type == typeof(int) && items.Equals(0))
             {
                 var loadedItems = howToGet();
                 _cachePolicy.Add(key, loadedItems);
                 return loadedItems;
             }
 
             return items;
         }
 
         protected T GetOrAdd<T>(string key, Func<T> howToGet, DateTime dt) where T : class
         {
             var items = _cachePolicy.Get<T>(key);
             if (items == null)
             {
                 var loadedItems = howToGet();
                 _cachePolicy.Add(key, loadedItems, dt);
                 return loadedItems;
             }
 
             var type = items.GetType();
             if (type == typeof(int) && items.Equals(0))
             {
                 var loadedItems = howToGet();
                 _cachePolicy.Add(key, loadedItems, dt);
                 return loadedItems;
             }
             return items;
         }
     }

[转载]第二节 Memcached之MemcachedProviders(Enyim)客户端使用及测试

mikel阅读(1179)

[转载]第二节 Memcached之MemcachedProviders(Enyim)客户端使用及测试 – 小城岁月 – 博客园.

本节探讨问题:

  • MemcachedProviders简单介绍
  • MemcachedProviders如何配置使用
  • MemcachedProviders命中率测试

MemcachedProviders是对Enyim.Caching的再次封装,并加入了客户端计数器功能以及Session数据库管理功能。上一节已 经提供了下载链接,需要下载的朋友到前一节下载。Enyim也是应用比较广泛的Memcached .net客户端,和之前的Memchachedonet 客户端相比,分布式算法应该做了相应优化(具体可参照第一节的原理环节查看),这一点我们在后面的测试环节做一下验证。我们先来看一下Enyim的基本业 务类图

以上为Enyim的基本业务类,开发中可直接使用MemcachedClient类+配置文件 完成基本的存取删除业务。其中ServerPool从配置文件读取服务器列表维护到MemCachedNode中,并且可以标记出哪些处于活动,哪些停止 响应的服务器从而方便客户端快速找到可以正常使用的服务器。在Operation类中,可以看到Enyim已经使用了二进制协议。

二、MemcachedProviders如何配置使用

如果喜欢简洁的可以直接使用Enyim.Caching开发,我们这里使用对Enyim.Caching再次封装的MemcachedProviders,因为他用来显示的更简洁。

简单的列一下MemcachedProviders 的几个基本类

DistCache 直接CURD的数据的静态类

MemcachedCacheProvider 策略模式提供的给DistCache的业务类

CacheProviderSection 缓存配置文件节点类

上图显示了MemcachedProviders的基本业务流程,我们在使用DistCache时,他首先会从配置文件找到对应的缓存策略 Providers,MemcachedCachedProvider是实现了计数器功能的一个策略,当然你也可以继承CacheProviders重写 一个策略类,而该类只需要实现MemcachedClient就可实现基本的业务。MemcachedClient被实现的时候,会实现默认的 ServerPool 去读取Enyim节点的服务器配置信息。很简单吧,那我们就开始测试环节的工作了。

三、MemcachedProviders命中率测试

MemcachedProviders源码是GIT上载的,GIT的项目基本上都是SVN搭建的,解压后会看到Branches(项目分支),Tags(里程),Trunk(项目主线)

我直接选了主版本Trunk的源码解决方案,新建设了一个Demo测试项目。

开始工作前我们参照上节,分别用MemcaheD Manager在3台服务器上搭了Memcached服务端

测试代码同上节一样,100条记录存取,分别3,4,5服务器测试。

View Code

配置文件先设置3台服务器

View Code

测试结果1:

MemcacheD Manager结果:

测试2:MemcacheD Manager清空所有服务器数据,在增加一台服务器继续测试,代码部分相同

配置文件:

View Code

测试结果2:

测试3:再增加至5台Server

配置文件:

View Code

测试结果:

看下工具的结果:

3次测试结果,100条记录分布在不同的Server上,Hit 100% MISS 0次。结果还是很理想的,看来Enyim改进的算法还是很优秀的,加上配置化,计数器等功能总体上优于Memcachedonet。

我们来看下MemcachedProviders计数器结果:

好了,这一节就到这里了。

[转载]10年软件开发教会我最重要的10件事

mikel阅读(869)

[转载]10年软件开发教会我最重要的10件事(转) – 风舞清涟 – 博客园.

0. “面向对象”比你想象的要难得多

也许只有我有这种想法,不过我曾经以为计算机科学课上学过的“面向对象”是很简单的东西。我的意思是,创建一些类来模拟现实世界能有多难啊?其实,那还真是挺难的。

十年之后,我仍然在学习如何合理地建模。我后悔以前我没有花更多的时间来学习面向对象和设计模式。优秀的建模技术对于每一个开发团队都是非常有价值的。

1. 软件开发的难点在于沟通

这里的沟通是指与人的沟通,而不是socket编程。有时你的确会遇上棘手的技术问题,但是这种情况根本不常见。常见的问题在于那些你和项目经理之间的、你和客户之间的、还有你和其他开发者之间的误解。培养你的软技能吧。

2. 学会拒绝

当我刚开始工作的时候,我非常急切的想要去讨好别人。这也就是说,我几乎不能去回绝别人对我的要求。我加了很多班,但是还是不能完成他们交代给我的所有事情。结果他们表示不满意,而我也表示要崩溃了。

如果你从不回绝别人,你的答应就显得毫无意义。承担能力所及的事情,如果别人不停地指派给你更多的事情,你需要明确的表示那意味着将会耽误其他的工作。

为了应付这种事情,我会随身携带一张列有待办事项的纸(To-do list)。当人们叫我去做什么事情的时候,我就给他们看这张纸,并且问他们我应该为他们挤掉哪个事情。这是我用来拒绝别人的一种好办法。

3. 如果每件事都重要,那就什么事都不重要

我们这一行,总是强调每种特性都是同等重要的,其实并不是这样。敦促你的同事,让他们承担起工作。

如果你不强迫他们选择该做和不该做的事情,你会轻松很多。相反,让他们来为你选择你这周的任务。这会让你生产出来的东西变得最有价值。如果其他的部分都还是乱糟糟的,至少你已经完成了最重要的。

4. 不要过度考虑问题

我可以站在白板前面一整天策划事情,但是这并不意味着事情会向更好的方向发展,这仅意味着事情将变得更复杂。

我的意思并不是“你不应该去做任何策划”,只是如果我会在实现程序的时候会很快遇到我没考虑过的问题的话,那为什么我不去尝试把它做好呢?像戴夫·法洛所说的,“魔鬼居住于细节中,而驱走魔鬼的方法是实践,而不是理论”。

5. 去钻研一些东西,但不要钻牛角尖

克里斯和我花费了大量的时间钻研SQL服务器的深层部分。那真的很有趣,我也学到了很多知识,但是过了一段时间我意识到,知道了那么多的知识并不能帮助我解决业务上的问题。

举个例子:我知道在数据表层次,SQL服务器不会接受IU锁——它只会接受IX锁。这是一个性能调整,因为在大多数情况下,IU锁都会升级成IX锁。为了了解这些,我花掉了无数天做实验,我读了很多的书,还在会议上向微软的员工了解情况。然而我用过这个知识吗?没有。

6. 了解软件开发系统的其他方面

这对成为一个优秀的开发者是很重要的,但是若要在一个开发软件的系统中成为优秀的一员,你还需要去了解开发系统中剩下的部分在干什么。QA是如何工作的?项目经理在干什么?业务分析员在忙些什么?这些知识会让你与其他员工产生联系,并使你和他们之间的互动顺畅。

向你周围的人寻求帮助,以便学到更多的知识。有什么好书呢?大多数人都会为你的关注而高兴,并且很乐意帮助你。在这上花一点小时间会对你有很大的帮助。

7. 同事是你最好的老师

在我找到第一份工作的一年后,我们和另一所公司合并了。突然之间身边就多出很多聪明又经验丰富的人。我深刻的记得这是我感到多么自卑和愚蠢。我努力地学习,读了一本又一本的书,还是还是赶不上他们。我发现他们和我比起来有非常突出的优势。

现在,我不会因为和优秀的人一起工作而感到难受。我认为我有一生的时间去学习。我提出问题,并且非常努力地去了解我的同事们是怎么做出结论的。这也是为什么我加入了ThoughtWorks。把你的同事们看成财富,而不是竞争对手

关于学习,不论是哪个行业,都是永恒的话题,正如 Jonathan Danylko在总结自己20年的编程经验时所说到,“诚然,总有很多你不知道的技术,你可以从中学习以保持不落后。如果你有一种灵巧的方式来获取你需要的新技术,那你每天都应该坚持学习。”(编注:ThoughtWorks是一家全球知名的IT咨询公司。)

8. 做出可用的软件是最终目标

不管你的算法有多酷,不管你的数据库模式有多棒,不管你的什么什么有多么多么好,如果它不能搔到客户的痒处,它就不值一文。专注于做出有用的软件,同时准备继续做出后续软件,这才是正轨。

9. 有些人真的不可理喻

在你身边的大多数人总是很优秀的,你向他们学习,他们也向你学习。共同完成一件事情的感觉总是很好。然而不幸的是,你也有可能遇到例外。因为某些原 因,人可能会变得冷漠刻薄。萎靡不振的老板啊,满口谎言的同事啊,无知愚昧的顾客什么的。不要把他们看的太重。尽量避开他们,尽量把他们所带来的痛苦和影 响降到最小,但不要自责。只要你保持诚实并且尽力去工作,你就完成了你该做的事情。

[转载]程序员的职业规划书

mikel阅读(1008)

[转载]我的职业规划书 – 九妹 – 博客园.

下海做程序员的第一步也是最重要的一部,如何订制自己的程序之路。
很多人在一谈到自己的计划的时候,都会去看看别人是怎么做的,一味的跟随别人的规划,多少岁之前做coder,多少岁之前做manager.其实每个人都有自己的特点,你应该停下来好好的审视自己的职业,不要跟着别人的路去走了,你应该知道自己要何去何从.

我们的职业之路要怎么制定呢?毕竟程序员是一门职业,作为软件的开发人员,我们就是一个从事某一个职业的工人,公司雇佣我们,绝对不是因为公司爱我 们。虽然天天公司教导我们“公司我是家”但是深圳的住房公积金,公司的交的那部分,还是转嫁给我们自己承担。事实上,公司以前从没有爱过我吗,将来也绝对 不会。公司是你自己的那就另当别论了,否则,程序员就不是一个职业了,职业不就每天要我们去一个地方,呆上8个或者更多的小时,牺牲大量的脑细胞或者汗 水,然后领取报酬吗?职业就是生意,把我们做的生意说的惨淡点,就是出卖自己i的劳动力,换钱,再高级的白领也是如此。当然做生意有赚有亏得,想要在这个 行业里面成为佼佼者,那就是必须要知道自己应该如何去做这门生意,如何为自己创造利润?

如果把你的职业人生想象成为一个你正在开发的软件产品的生命周期,现在你的所有需求都已经明确(有车,有房,有钱,有公司等等),接下来我们就要开 始职业人生的设计了,在制定这个规划的时候,我们要重要的注意以下4个方面的内容,这个四个方面运用到整个人职业的生命周期中。

一、选择市场。 一定要谨慎的挑选你要关注的技术和商业领域。如何权衡风险和收益?
都是做软件开发,你究竟要做与硬件相关的还是与网络相关的?与手机相关的还是与汽车相关的?每一个分支都有专家和权威,你要确认自己想站在哪一个分支的顶点。在深圳很多程序员,为了生存,先入行再转行。程序员需要积累,面试官不喜欢一张白纸上满是编程理念的空头支票。

二、投资。

做生意哪有不投资就赚钱的好事,你的知识和技术就是你这件生意的基础。所以你要在这两个方面合理的投资,时间,金钱。只知道在理论上使用VB或者Java已经远远不够了,那么在新的环境下,新的平台下,又有哪些新的技术你应该具备的呢?

三、执行力。

用我老板的话来说单纯有技术出色的员工,并不能给公司带来利益。员工必须要有产出才行。有的时候一名优秀的员工产出远远不及一名普通的员工,反而有 时候会让简单的事情变的一团糟糕,2分钟一个简单的算法,被花上2天时间提高0.001%的效率这种事情也是经常发生的。所以我们应该考虑的是能否创造最 有利的价值而不是完美,

四、团队 。

程序员孤军奋战成不了大事。一个再优秀的程序员也完成不了整个windows操作系统的工作,虽然我见过一个人是可以独立完成破解windows的工作的。所以如果不想过于孤单和山寨,请找到一支正规军加入他们。

五、又是市场。

你们肯定会说,你开始写循环了是吧?怎么又是市场?
一个人选对了市场,投资技术,有了回报,有了产出,有了自己的团队,恭喜你,你离出产品 的日子不远了。但是你有没有考虑一下你的产品的市场,若是无人知晓,毫无用途,又怎么会有利润呢?你的成绩又怎么会被老板和同行认可呢?请记住:一个团队 奋斗了1个月写出来一个:Hello world!是赚不了钱的。

[转载]Asp.net mvc 网站之速度优化 -- 页面缓存

mikel阅读(1071)

[转载]Asp.net mvc 网站之速度优化 — 页面缓存 – enjoyeclipse – 博客园.

网站速度优化的一般方法

由于网站最重要的用户体验就是速度,特别是对于电子商务网站而言。

一般网站速度优化会涉及到几个方面:

1. 数据库优化 — 查询字段简历索引,使用数据库连接池和持久化,现在还有种趋势,就是选择使用No SQL作为补充;

2. 数据缓存 — 使用Memcached等;

3. 负载均衡 — 使用ngnix等

4. 页面缓存 — 将.aspx, .jsp等动态页面缓存或静态化为.html页面

5. 前端优化 — Yahoo 14条前端优化原则。

城江湖(Incity.me)针对 2 数据缓存, 4 页面静态化, 5 Yahoo 14条优化原则做了具体的实践,并获得了实际效果,以后的系列文章会举出一些实践方法和列出部分代码,这次主要针对页面缓存进行说明。

哪些地方需要页面缓存?

以InCity为例,首页商品分类帮助中心等都是用于展示商品和网站信息的,与用户的交互相对较少。在某个时间段内(1小时),所有用户看到的页面都应该是相同的, 并不会因为不同的用户而显示不同的信息。

全局页面缓存 OutputCache

InCity是基于ASP.NET MVC开发的,熟悉ASP.NET MVC的童鞋都知道,ASP.NET MVC自带了一个属性叫OutputCache,  最常用的是Duration和VaryByParam两个参数:

MSDN:

Duration:表示页或用户控件进行缓存的时间(以秒计)

VaryByParam:分号分隔的字符串列表,用于使输出缓存发生变化。

Code:

[OutputCache(Duration=”3600″ VaryByParam=”type”)]

public ActionResult Catalog(string type)

解释一下:

1. 用户第一次输入http://incity.me/catalog/food,从后台获取,并为catalog/food生成缓存页面,3600秒内缓存页面有效。

2. 用户再次输入http://incity.me/catalog/food,从缓存页面获取。

3. 当用户第一次输入http://incity.me/catalog/play的时候,因为{type}从food变成了play,数据从后台获取,并为catalog/play生成缓存代码3600秒内有效。

4.用户再次输入http://incity.me/catalog/play,从缓存页面获取。

局部页面缓存 PartOutputCache

上 述的解决方法对于大部分都可以处理,但是如果遇到下面的情况怎么办?登录前首页右侧的面板是显示登录区,登录后是显示用户信息,而首页如果采用 OutputCache全局页面缓存的话,则右侧显示不同的账户信息的。因为前面我们已经提到,在某个时间段内(1小时),所有用户看到的页面都应该是相 同的。

登录前:

登录后:

这时候就需要针对左侧的商品作局部缓存,而对右侧不使用缓存。如何达到这个效果呢?遗憾的是,这时候微软官方的ASP.NET MVC并未提供这种功能,因此参考使用了PartOutputCache,用法如下:

[PartOutputCache(CacheDuration = 3600)]

public ActionResult ShowCase()

aspx页面代码则变成了

<div id=”Container”>

<!–使用了缓存–>

<%Html.RenderAction<HomeController>(p => p.IndexShowCase());%>

<!–没有使用缓存–>

<%Html.RenderAction<HomeController>(p => p.LoginPanel());%>

</div>

转载自: dev.incity.me

PartOutputCache源代码看这里

[转载]最专业的通用.NET插件平台——尤埃开放服务平台介绍

mikel阅读(930)

[转载]最专业的通用.NET插件平台——尤埃开放服务平台介绍 – 道法自然 – 博客园.

尤埃开放服务平台(UIOSP)是基于.NET设计的插件化平台。该平台设计的初衷是: (1)为所有.NET应用环境设计一个通用的插件平台,即该平台能够以标准化的插件规范来开发基于.NET Framework的控制台应用、WinForm应用、ASP.NET应用、WPF应用、Windows服务应用及SilverLight应用和基 于.NET Compact Framework的移动应用设计;(2)为基于.NET的统一开放平台提供支持,即开发人员基于该平台设计的可完全复用的插件可以通过统一开放平台开放 给用户,这样开发者或者最终用户可以从该平台获取需要的模块然后组装成最终软件;(3)为企业构建一个基于插件库的标准化的软件生产线,用于支持软件产品 自动升级、远程部署、远程管理、统一版本、局部更新、知识积累。

UIOSP插件平台通过对.NET CLR进行扩展实现优雅的通用的插件化框架,它支持模块化与插件化、面向服务架构、模块扩展三大功能。模块化与插件化为.NET应用程序提供了物理隔离的 模块支持,它为每一个物理隔离的模块提供了标准的规范、隔离的目录结构、隔离的类加载器、多版本并存支持、插件依赖支持等功能;面向服务架构是实现模块化 通讯的手段,每一个模块通过服务总线来注册/查询绑定/卸载服务,服务是模块间交互的手段。在该平台,服务是可管理的,这意味着插件间的交互可以被管理和 监控。模块扩展功能为插件提供了可扩展机制,这样我们可以在不改变原有模块的代码情况下,来注入新的功能或更新原有功能。

你可以从插件平台这 个链接下载到该平台的安装包,一旦安装后,它将为你提供:(1)用户开发指南;(2)Visual Studio标准项目模板,可用于创建不同应用环境的主程序和插件;(3)基于Visual Studio的插件配置工具,用于插件可视化配置;(4)远程控制台,可用于查看插件内核的插件状况,动态安装/启动/停止/卸载插件。

image

下 图是基于该插件平台的软件系统的通用架构。在这里你根据应用系统的环境,创建相应的主程序,并利用UIOSP的BundleRuntime类来启动插件框 架。在UIOSP,插件用英语单词Bundle来表示,Bundle可以翻译为插件或者模块,而BundleRuntime就是插件运行时了,这与WWF 的WorkflowRuntime概念类似。一旦插件框架被启动,它将会加载位于plugins目录下的所有标准化的插件,并将插件组装成一个应用系统。 应用程序的开发可以按2个步骤走:(1)创建主程序;(2)创建插件。

image

下图则是基于插件库的企业级应用系统架构。在这里,企业将建立自己的私有插件/模块仓库,构建自己的产品生产线,使用一致的方式来构建、维护、部署、升级、管理软件产品。

image

接下来以一个Demo来演示一下如何来演示这个插件框架的使用方法。

首先运行Visual Studio,然后使用向导创建一个“UIOSP”=>“高级Windows窗体应用程序”项目。

image

这样你就使用UIOSP提供的项目模板创建了一个默认的WinForm插件主程序了。

image

你 可以发现创建的主程序包括:Program.cs启动类、bin/plugins目录及该目录下的三个默认插件。Program.cs类在这里完成的工作 很简单:(1)创建一个BundleRuntime并调用Start方法来启动插件内核;(2)从插件内核服务总线中获取一个类型为Form的服务,即主 窗体,然后运行该主窗体。一旦程序启动,那么在bin/plugins目录下的插件会被BundleRuntime加载并启动。这个项目里面有一个 WinFormShellPlugin插件,该插件是一个通用的WinForm主窗体,该主窗体实现了菜单、导航栏、内容区域、状态栏,并支持换肤。你可 以试一下启动这个程序,结果如下。

image

这 个主程序包含的WinFormShellPlugin插件已经为你提供了一个漂亮的防Office的Windows空的壳子。下面我们来试着开发一个应用 插件。回到Visual Studio,选中解决方案然后点击“添加新建项目”,选中“UIOSP”=>“高级Windows窗体插件”,命名为AppPlugin。需要注 意的是,这个AppPlugin插件项目必须位于bin/plugins目录下。

image

浏览一下这个AppPlugin插件项目,其内容如下。插件包含一个Activator.cs、Manifest.xml、一个窗体、一个用户控件和一个资源。

image

在 插件中,Manifest.xml是插件的配置文件,它用于声明插件的标识、名称、启动顺序、初始启动状态、本地类库、依赖的插件和类库、扩展信息。双击 插件,你可以使用基于Visual Studio的插件配置工具来查看和更改配置信息。如下图所示。它包含四个标签页:(1)基本:用于配置插件的基本信息;(2)运行时:用于配置插件需要 的类库、依赖的插件或依赖的插件的类库信息;(3)服务:用于配置插件提供的服务;(4)扩展:用于定义插件的扩展点和对其它插件的扩展信息。

image

按 F7可以查看Manifest.xml的源代码,如下所示。<Bundle>节点定义基本信息,<Activator>节点定义 指定插件执行入口和出口的类型,其定义就是这个项目的AppPlugin.Activator类型,<Runtime>指定了这个插件的本地 类库,<Extension>节点定义了对WinFormShellPlugin的扩展,它向这个插件的左边的导航栏注册了2个菜单和菜单点 击时显示的窗体/用户控件的类型。

1 <?xml version=”1.0″ encoding=”utf-8″ ?>
2 <Bundle xmlns=”urn:uiosp-bundle-manifest-2.0″ SymbolicName=”AppPlugin” Name=”AppPlugin” Version=”1.0.0.0″ InitializedState=”Active”>
3 <Activator Type=”AppPlugin.Activator”/>
4 <Runtime>
5 <Assembly Path=”bin\AppPlugin.dll”/>
6 </Runtime>
7 <Extension Point=”UIShell.Applications”>
8 <Application Title=”AppPlugin” ToolTip=”AppPlugin” Icon=”AppPlugin.Resources.shell.png”>
9 <Menu Text=”UserControl1″ ToolTip=”UserControl1″ Icon=”AppPlugin.Resources.shell.png” Class=”AppPlugin.UserControl1″/>
10 <Menu Text=”Form1″ ToolTip=”Form1″ Icon=”AppPlugin.Resources.shell.png” Class=”AppPlugin.Form1″/>
11 </Application>
12 </Extension>
13 </Bundle>

这 个插件的Activator.cs文件定义了插件的入口和出口。当插件被启动时,这个类的Start方法会被调用并传入一个插件上下文参数 (IBundleContext);反之,如果插件被停止,Stop方法被调用。IBundleContext这个对象是插件与内核交互的唯一参数,你可 以通过它来注册/查询/绑定/卸载服务;可以通过它来或者这个插件对应的Bundle对象;可以通过它来查询插件内核的插件情况,动态安装/启动/停止 /卸载插件;可以监听插件内核的各种事件。接下来,你可以试着运行一下这个应用程序了。

image

你 可以看到,构建的插件向WinFormShellPlugin的导航栏注册了由“UserControl1”和“Form1”两个菜单项组成的 “AppPlugin”菜单组,一旦点击“UserControl1”菜单,这个用户控件就显示在右边的内容区域。随着你构建越来越多的插件,他们将向界 面中注册越来越多的菜单和窗体,那一个基于插件平台的具有漂亮界面的WinForm应用程序构建完成了。不过,还没完,下面你还可以试着使用远程管理控制 台工具来管理插件内核。为了更好演示动态性,我又创建了一个DemoPlugin插件。

在这里,你可以使用install/list/start/stop/uninstall指令来操作。首先,输入list来查看插件内核加载的情况。如下所示,它列出了5个插件,当然有一个没有显示,就是ID为1的系统插件。

image

接下来你可以使用stop 2/start 2/uninstall 2来停止AppPlugin/启动AppPlugin/卸载AppPlugin。下面看一下Stop 2指令即停止AppPlugin的效果。

image

你 可以发现AppPlugin这个插件已经被停止,它创建的菜单也从界面上消失。这就是UIOSP的另一重要特性:动态性!你可以通过远程控制指令来更改软 件的行为。有关UIOSP这个最专业的插件平台的介绍,先到这,后面我将介绍UIOSP构建的一个实际的案例——SaaS应用商店开放平台,它使用的是基 于插件仓库来构建的开放平台。

有任何问题欢迎加入UIOSP交流群进行讨论,群号:121369588。

转载Android中包含多个Activity的应用退出按钮实现

mikel阅读(1139)

转载Android中包含多个Activity的应用退出按钮实现 – deaboway – 博客园.

Android编程中,application这样的名词似乎变得那样的不常见,而让大家更为熟悉的是activity、intent、 provider、broadcast和service。但其实Android中的application也有着它自身的用处。打开manifest文 件,会看到有一个application配置标签,这就是有关application的使用了。

就是说application是用来保存全局变量的,并且是在package创建的时候就跟着存在了。所以当我们需要创建全局变量的时候,不需要再像j2se那样需要创建public权限的static变量,而直接在application中去实现。只需要调用Context的getApplicationContext 或者Activity的getApplication 方法来获得一个application对象,再做出相应的处理。

退出按钮实现

首先,创建Application来存储所有打开的Activity的list。代码如下:

package com.deaboway.view;  
import java.util.ArrayList;  
import java.util.List;  
import android.app.Activity;  
import android.app.Application;  
public class Deaboway extends Application {  
    private List<Activity> mainActivity = new ArrayList<Activity>();  
    public List<Activity> MainActivity() {  
        return mainActivity;  
    }  
    public void addActivity(Activity act) {  
        mainActivity.add(act);  
    }  
    public void finishAll() {  
        for (Activity act : mainActivity) {  
            if (!act.isFinishing()) {  
                act.finish();  
            }  
        }  
        mainActivity = null;  
    }  
} 

其次,在所有Activity的 @Override public void onCreate(Bundle savedInstanceState) {}方法中加上:

      public void onCreate(Bundle savedInstanceState) {  
          super.onCreate(savedInstanceState);  
    Deaboway appState = (Deaboway)this.getApplication();  
    appState.addActivity(this);  
          setContentView(R.layout.main);  
         。。。。。。。  
      }  

第三,在退出按钮的地方调用:

   OnClickListener() {  
                public void onClick(View v) {  
                    Deaboway appState = (Deaboway)getApplicationContext();  
                    appState.finishAll();  
                }  
            }  

最后,要记得在manifest中的application标签中添加 android:name=”.Deaboway”

[转载]Android上OpenGL开发一些经验记录(上)

mikel阅读(1119)

[转载]Android上OpenGL开发一些经验记录(上) – YYX – 博客园.

Android沿用了J2ME的OPENGL ES API.

相比C版本的OpenGL,Opengl ES 没有glu和glut库,而且只能画三角形(多边形需要三角化)。

没有直接的drawXXX 方法,只有通过 glVertiexPointer传入顶点画图。

另外参数上,没有指针和C风格的数组,Java需要用Buffer类来代替这个。

先看Android的glVertexPointer :

GL10.glVertexPointer(int size, int type, int stride, Buffer pointer):

这个方法为 后面openGL绘图准备顶点数据。

size : 代表每个顶点包含几个坐标参数 ,如pointer的buffer中只含有 x,y坐标, 则传2, OpenGL会默认使用0作为z坐标。如果包含 x,y,z 坐标,则传3。其他值在这里都不适用。
type : 是一个枚举值,可以为 GL_FLOAT和 GL_FIXED,浮点数可对应java 的 float,要求pointer为 FloatBuffer.
GL_FIXED意为定点数,长度4字节,高16位表示整数部分,低16位表示小数部分。传入int值前需要先左移16位(即需扩大 0x10000倍)。要求pointer为IntBuffer.
stride :指每个元素之间,间隔多少个值。加入buffer中坐标点数值间紧密相连,那么stride就是0,如果点1,点2间还有不用到的值,则stride就是这种值的个数。
pointer:这是最需要注意的一个参数,也是Java版OpenGL特有的。Buffer类型是一个基类,具体的类型是 FloatBuffer还是IntBuffer要根据前面type参数来决定。
Java中的 Buffer分两种,一种direct,一种非direct.这里只支持 DirectBuffer,也就是通过ByteBuffer.allocateDirect(int cap) 分配而来的buffer.
通过allocateDirect 得到的是一个 ByteBuffer,实际使用时,如果要作为FloatBuffer,可以通过 ByteBuffer.asFloatBuffer来得到,IntBuffer也同样。
做到这些当然还不够,ByteOrder也对这个参数有影响。当的ByteBuffer作为FloatBuffer,则float的4字节默认是按照小端排列在directBuffer中,在
某些大端的设备中这个buffer的格式就不正确,需要根据设备设置ByteOrder.
所以以FloatBuffer为例,创建方法如下:
FloatBuffer buffer = ByteBuffer.allocateDirect(1024).order(ByteOrder.nativeOrder()).asFloatBuffer();
有了FloatBuffer,我们还需要将实际顶点坐标传入这个buffer。这只需要调用 FloatBuffer.put(float)的方法即可。
注意放顶点坐标是x,y…的格式,还是x,y,z…的格式要和前面第一个参数 size是2还是3统一。
所有的值放完以后,需要调用 buffer.rewind()或者 buffer.position(0),将buffer内游标置回0,否则OpenGL会从最后一次put的下一个位置开始读取。
关于三角化的算法:
Android的OpenGL API 画多边形目前只支持 triangle_fan,triangles, triangle_strip 三种。如果只有简单无洞的凸多边形,只需要将所有点当作triangle_fan的顶点就可以画出。
如果存在凹多边形,就需要进行三角化(当然凸多边形也可以三角化,保持逻辑上的统一)。
有个最简单的三角化算法叫做 ear clipping三角化。几何上非常容易理解:
一个多边形的一个顶点,和它相邻两个顶点可以组成一个三角形,如果这个三角形内部不存在这个多边形的其他顶点,就可以把这个顶点和相邻点组成的三角形当作一个ear.
这个ear可以被切下来(沿两个相邻顶点切)。每切一次,得到一个三角形和一个少了一个顶点的多边形,然后再对这个多边形做同样操作,直到剩下的这个多边形也只剩下3个顶点。
如此一来,这个多边形被完全分解为3角形。
要把把几何上的操作变成代码,只要解决这几个问题:
#如何判断多边形的一串顶点是逆时针还是顺时针排列的?
– 从某个顶点指向它下一个顶点,可以得到一个向量,多边形有几条边就得到几个向量,如果所有相邻两个向量的叉积(前一个向量和后一个向量的叉积)之和大于0,则排列是逆时针的,反之是顺时针的
(根据右手坐标系判断,一系列逆时针向量围成的面积是指向z轴正向的),为0有两种情况,这串点是直线,或者多边形某两条边交叉,这种多变形不符合这个三角化算法的条件。
#根据顶点顺逆情况,调整顶点排列,保证逆时针排序,则可以得到如下结论:
– 如果相邻两个向量,前一个向量和后一个向量叉积,值为正,则两个向量连接点这个顶点是凸点,值为负则为凹点。
– 如果有相邻3个顶点 p1,p2,p3 组成三角形,有另外一个顶点 P,如何判断P是否在三角形内?
分别做如下几个叉积p2P X p1p2, p3P X p2p3 , p1P X p3p1 ,如果这3个叉积同为正或同为负,则这个顶点在三角形内部。
关于 glEnableClientState, glDisableClientState,
glEnableClientState(int cap);
cap : GL_COLOR_ARRAY
GL_EDGE_FLAG_ARRAY
GL_FOG_COORD_ARRAY
GL_INDEX_ARRAY
GL_NORMAL_ARRAY
GL_SECONDARY_COLOR_ARRAY
GL_TEXTURE_COORD_ARRAY
GL_VERTEX_ARRAY
是用来启用或者关闭和这些数组功能。
如同前面的glVertexPointer ,还有别的诸如 glColorPointer, glEdgeFlagPointer等等接口,
glVertexPointer描述顶点位置,其他的描述顶点或者平面的属性。
这些数组默认都是disable状态,如果用这两个接口enable了某个数组,那么当glDrawArrays 调用之前必须把相应的数组准备好。否则draw不能成功。
所以如果不准备传入某个数组,draw之前要先 disable这个数组(如果前面enable过)。
反之如果要使用某个数组,也要事先enable。

还有Java中缺少的API,比如没有glPerspective的时候如何用glFrustm实现glPerspective,以及没有gluLookAt的时候如何用modelView来得到同样效果。将在之后文章里面解说。