Posted on

CSS Vertical Align(用純CSS解決div垂直置中)

本文出處:http://blog.yam.com/hanasan/article/35806444

本次要介紹的是CSS垂直置中(Vertical Align with css)的完整解決整理。
說實話這並不太容易,雖然不像水平置中 {margin:0 auto;} 那樣單純, 但仍有幾種方式可以作到,以下共有五種方式一一介紹。

每種使用方式各有其優、缺點,端看自己要置中的內容是「區塊」或是「文字」來取捨。

方法一

使用CSS table-cell屬性來完成,什麼是table-cell?簡單說就是針對一些html object附于它table的屬性(詳見此), 如果曾經使用過table來排版的網頁開發者,應該知道td的既有屬性valign,古早以前根本不會有垂直置中的問題,因為td下個 valign=”middle”就行了。 而table-cell即是可以將div模擬成表格(table)的儲存格(td),讓原本不存在vertical-align的div可以使用。

Sample Code

HTML

<div id="wrap">
    <div id="cell">
        <div id="content">
            要被置中的內容
        </div>
    </div>
</div>

CSS

#wrap { display:table; }
#cell { display:table-cell; vertical-align:middle; }

優點:

  1. 因為是CSS2.1釋出的標準屬性,正規的解決方法。
  2. 被置中的內容增加後,垂直置中的block會自動調整。

缺點:

  1. 支援性不佳,IE8以上才支援(IE7以下不支援display:table語法)
  2. 太多巢狀標籤(有種回到過去table排版的fu)

方法二

此方法適用在定義了絕對定位(absolute)的div, 將其top設置為50%, 再設置與div高度一半的「負」值margin-top,意謂著使用本方法必須固定div的高度。

Sample Code

HTML

<div id="center">
    要被置中的內容
</div>

CSS

#center {
    position:absolute; height:400px; top:50%; margin-top:-200px; /* div高度的一半 */
}

優點:

  1. 程式碼簡短,且無需為了「垂直置中」的目的多寫巢狀標籤
  2. 所有browser都支援,泛用性高

缺點:

  1. div高度需固定,若是動態資料有可能超過的話需要加上overflow:scroll讓溢出的內容可以看見

方法三

 

在需要被垂直置中的div前放置另一個div,設置為height:50%,margin-bottom:-contentHeight(目標高度的負值)

Sample Code

HTML

<body>
    <div id="floater"></div>
    <div id="middle">
        要被置中的div
    </div>
</body>

CSS

html, body {
    margin:0; padding:0; height:100%;
}
#floater { float:left; height:50%; margin-bottom:-200px;
    width:1px; /* only for IE7 */
}
#middle {  clear:both; height:400px; position:relative; }

優點:

  1. 所有browser都支援(Note:IE7必須在#floater追加width:1px才work!)
  2. 當內容增加時,垂直置中的div不會被切掉,而是會自動出現scroll-bar

缺點:

  1. 沒甚麼缺點,真要說就是一樣高度得固定。另外若置中物件的父層是body, 即使視窗被USER拖曳拉小了,div也一樣會唯持置中(笑)

方法四

本法使用在同樣是絕對定位(absolute)的div上,固定高度,並定義top:0; bottom:0; 和廣為被應用的
{ margin:0 auto; }作div水平置中原理類似

Sample Code

HTML

<div id="middle">
    我要被置中啦~
</div>

CSS

#middle {
    position:absolute; width:70%; height:280px;
    top:0; bottom:0; left:0; right:0; margin:auto;
}

優點:

  1. 簡單

缺點:

  1. 不支援IE7(含)以下
  2. 如果容器不夠裝內文, 也不會有scrollbar自動出現…

方法五

此方法適用於「單行」文字的垂直置中(EX:要作英文網站大Slogan時), container除了設置高度之外,同時也將行距(line-height)設置與高度相等。

Sample Code

HTML

<div id="content">
    一行文字要被置中啦
</div>

CSS

#content { font-size:32px; text-align:center; height:150px; line-height:150px; }

優點:

  1. 簡單
  2. 所有browser都支援(even IE6!)
  3. 即使內容溢出也不會被切掉

缺點:

  1. 只有單行文字適合
  2. 若div寬度固定,一當有長文字爆行時會很醜,務必小心使用。

以上列出五種使用純CSS(不加js)達成div vertical align(垂直置中)的藥方,可以綜合搭配使用,也可視情況單獨使用…

Posted on

JQuery選擇器

1. 選擇所有的table

$(document).ready(function() {
     $('table tr').filter(function(index){
          //....
     });
});

2. 選擇第N行(若有很多table則只會選第一個table的第N行)

$(document).ready(function() {
     $("tr:eq(1)").addClass("mytr");
     $("tr:eq(2)").css('background-color','#663300');
});

3. 選擇第N行(若有很多table則會選擇每個table的第N行)

$(document).ready(function() {
     $("table tr:nth-child(1)").addClass("mytr");
});

4. 選奇偶行

$(document).ready(function() {
 $("table tr:odd").addClass("trOdd");
 $("table tr:even").addClass("trEven");
});

3. 選第一個元素

$(document).ready(function() {
 $("table tr:first").addClass("trFirst");
 $("table tr:last").addClass("trLast");
});

下面是相關選擇器的一個小範例

<html>
	<head>
		<script Type="text/javascript" src="js/jQuery.js"></script>
		<script Type="text/javascript">
			$(document).ready(function(){
				$('#btn1').click(function(){
					$('tr:even').removeClass();
					$('tr:even').addClass('myEven');
				});
				$('#btn2').click(function(){
					$('tr:odd').removeClass();
					$('tr:odd').addClass('myOdd');
				});
				$('#btn3').click(function(){
					$('tr:eq(1)').removeClass();
					$('tr:eq(1)').addClass('myEq');
				});
				$('#btn4').click(function(){
					$('#tbd tr:even').removeClass();
					$('#tbd tr:even').addClass('myEven');
				});
			})
		</script>
		<style type="text/css">
			.myOdd
			{
				background-Color:pink;
			}
			.myEven
			{
				background-Color:Yellow;
			}
			.myEq
			{
				background-Color:green;
			}
		</style>
	</head>
	<body>
		<input type="Button" id="btn1" name="btn1" value="測試Even">
		<br />
		<input type="Button" id="btn2" name="btn2" value="測試Odd">
		<br />
		<input type="Button" id="btn3" name="btn3" value="測試eq">
		<br />
		<input type="Button" id="btn4" name="btn4" value="測試tbody內的tr">
		<br />
		<hr />
		<table border="1">
			<thead>
				<tr>
					<th>1,0</th>
					<th>2,0</th>
					<th>3,0</th>
					<th>4,0</th>
					<th>5,0</th>
				</tr>
			</thead>
			<tbody id="tbd">
				<tr>
					<td>1,1</td>
					<td>2,1</td>
					<td>3,1</td>
					<td>4,1</td>
					<td>5,1</td>
				</tr>
				<tr>
					<td>1,2</td>
					<td>2,2</td>
					<td>3,2</td>
					<td>4,2</td>
					<td>5,2</td>
				</tr>
				<tr>
					<td>1,3</td>
					<td>2,3</td>
					<td>3,3</td>
					<td>4,3</td>
					<td>5,3</td>
				</tr>
				<tr>
					<td>1,4</td>
					<td>2,4</td>
					<td>3,4</td>
					<td>4,4</td>
					<td>5,4</td>
				</tr>
			</tbody>
		</table>
	</body>
</html>

下面是顯示的結果


1,0 2,0 3,0 4,0 5,0
1,1 2,1 3,1 4,1 5,1
1,2 2,2 3,2 4,2 5,2
1,3 2,3 3,3 4,3 5,3
1,4 2,4 3,4 4,4 5,4


相關文章:
jQuery 參考手冊 – 選擇器 (http://www.w3school.com.cn/jquery/jquery_ref_selectors.asp)

jQuery 選擇器

選擇器 實例 選取
* $(“*”) 所有元素
#id $(“#lastname”) id=”lastname” 的元素
.class $(“.intro”) 所有 的元素
element $(“p”) 所有 <p> 元素
.class.class $(“.intro.demo”) 所有 且 的元素
:first $(“p:first”) 第一個 <p> 元素
:last $(“p:last”) 最後一個 <p> 元素
:even $(“tr:even”) 所有偶數 <tr> 元素
:odd $(“tr:odd”) 所有奇數 <tr> 元素
:eq(index) $(“ul li:eq(3)”) 列表中的第四個元素(index 從 0 開始)
:gt(no) $(“ul li:gt(3)”) 列出 index 大於 3 的元素
:lt(no) $(“ul li:lt(3)”) 列出 index 小於 3 的元素
:not(selector) $(“input:not(:empty)”) 所有不為空的 input 元素
:header $(“:header”) 所有標題元素 <h1> – <h6>
:animated 所有動畫元素
:contains(text) $(“:contains(‘W3School’)”) 包含指定字符串的所有元素
:empty $(“:empty”) 無子(元素)節點的所有元素
:hidden $(“p:hidden”) 所有隱藏的 <p> 元素
:visible $(“table:visible”) 所有可見的表格
s1,s2,s3 $(“th,td,.intro”) 所有帶有匹配選擇的元素
[attribute] $(“[href]”) 所有帶有 href 屬性的元素
[attribute=value] $(“[href=’#’]”) 所有 href 屬性的值等於 “#” 的元素
[attribute!=value] $(“[href!=’#’]”) 所有 href 屬性的值不等於 “#” 的元素
[attribute$=value] $(“[href$=’.jpg’]”) 所有 href 屬性的值包含以 “.jpg” 結尾的元素
:input $(“:input”) 所有 <input> 元素
:text $(“:text”) 所有 type=”text” 的 <input> 元素
:password $(“:password”) 所有 type=”password” 的 <input> 元素
:radio $(“:radio”) 所有 type=”radio” 的 <input> 元素
:checkbox $(“:checkbox”) 所有 type=”checkbox” 的 <input> 元素
:submit $(“:submit”) 所有 type=”submit” 的 <input> 元素
:reset $(“:reset”) 所有 type=”reset” 的 <input> 元素
:button $(“:button”) 所有 type=”button” 的 <input> 元素
:image $(“:image”) 所有 type=”image” 的 <input> 元素
:file $(“:file”) 所有 type=”file” 的 <input> 元素
:enabled $(“:enabled”) 所有激活的 input 元素
:disabled $(“:disabled”) 所有禁用的 input 元素
:selected $(“:selected”) 所有被選取的 input 元素
:checked $(“:checked”) 所有被選中的 input 元素
Posted on

Flex裡綁定(Bindable)相關函數及使用方式

在flex裡,最強大的標籤應該就是[Bindable]的綁定標籤了
因為某次的需求,我需要研究將Bindable綁定至函數
也順便研究了ChangeWatcher和BindingUtils的使用

【BindingUtils】
官方的說明在此:
http://help.adobe.com/zh_TW/FlashPlatform/reference/actionscript/3/mx/binding/utils/BindingUtils.html
這是Flex內綁定的工具,裡面有兩個屬性,一個是綁定到函數(bindSetter),另一個則是綁定到某物件的某屬性(bindProperty)

使用範例如下
1. 綁定到函數(bindSetter)










2. 綁定到某物件的某屬性(bindProperty)










【ChangeWatcher】
官方的說明在此:
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/mx/binding/utils/ChangeWatcher.html
因為此次我們要綁定的函數裡是有帶多個參數的,因此BindingUtils的bindSetter便無法使用
這時就需要使用BindingUtils所用的ChangeWatcher來自己做綁定的動作
ChangeWatcher的使用方式如下
var model:Model = new Model();
watcherInstance = ChangeWatcher.watch(model,[“totalItems”],itemsChanged);
根據官方文件watch的傳入的東西依序為”要綁定的物件”、”要綁定的屬性”、”要綁定的函數”

下面便是我根據這些所寫的小範例
MyBindingUtils.as
package {
import flash.events.Event;
import flash.events.EventDispatcher;
import flash.system.Capabilities;
import flash.utils.getTimer;

import mx.binding.utils.ChangeWatcher;
import mx.controls.Alert;
import mx.resources.ResourceManager;

public class MyBindingUtils extends EventDispatcher {

private static var _objs:MyBindingUtils;

public static function getInstance():MyBindingUtils {
if (_objs == null) {
_objs = new MyBindingUtils();
}
return _objs;
}

public function changeLanguage(lang:String):void {
ResourceManager.getInstance().localeChain = [lang, “en_US”];
this.dispatchEvent(new Event(“ChangeLanguage”));
}

[Bindable(event=”ChangeLanguage”)]
public function getString(type:String, key:String, parameters:Array = null, locale:String = null):String {
return ResourceManager.getInstance().getString(type, key, parameters, locale);
}

public function bindString(target:Object, prop:String, type:String, key:String, parameters:Array = null):String {
var w:ChangeWatcher = ChangeWatcher.watch(this, [“getString”], null);
var result:String = getString.apply(null, [type, key, parameters]);
if (w != null) {
var invoke:Function = function(event:*):void
{
result = getString.apply(null, [type, key, parameters]);
target[prop] = result;
};
w.setHandler(invoke);
invoke(null);
}
return result;
}
}
}

完整範例檔案可按此下載

Posted on

在as3裡取得函數呼叫者資訊

補充:這個方法只可以在flash player的debugger版本可用,
因為在一般非debugger的player無法用”e.getStackTrace()”來抓取歷史資訊

再補充:非debugger的版本只需在flex的compiler arguments裡加上
-swf-version=18
這串參數,就會可以正確的取得”e.getStackTrace()”的值了!

如果我們在某個函數兩要知道有關傳進的參數的相關資訊
可以使用arguments去取得

下面網址有介紹arguments的使用方式
http://help.adobe.com/en_US/FlashPlatform/reference/actionscript/3/arguments.html

package {
import flash.display.Sprite;

public class ArgumentsExample extends Sprite {
public function ArgumentsExample() {
println(“Hello World”);
}

public function println(str:String):void {
trace(arguments.callee == this.println); // true
trace(arguments.length); // 1
trace(arguments[0]); // Hello World
trace(str); // Hello World
}
}
}

但是過去在as2裡,arguments可以用caller去知道呼叫此函數的地方
在as3裡,卻將此一屬性拿掉了。
那我們在as3裡該如何知道是誰呼叫了這個函數呢?

我在一個別人的部落格裡找到一個別人寫好的解法
是先丟出一個錯誤訊息,然後去getStackTrace(),再去解析之前呼叫者的資訊
try { throw new Error(); }
catch ( e: Error ) { stackTrace = e.getStackTrace(); }

原始部落格在此
Looking up the calling function

原始碼如下:
var stackTrace:String;

try { throw new Error(); }
catch (e:Error) { stackTrace = e.getStackTrace(); }

var lines:Array = stackTrace.split(“\n”);
var isDebug:Boolean = (lines[1] as String).indexOf(‘[‘) != -1;

var path:String;
var line:int = -1;

if(isDebug)
{
var regex:RegExp = /at\x20(.+?)\[(.+?)\]/i;
var matches:Array = regex.exec(lines[2]);

path = matches[1];

//file:line = matches[2]
//windows == 2 because of drive:\
line = matches[2].split(‘:’)[2];
}
else
{
path = (lines[2] as String).substring(4);
}

trace(path + (line != -1 ? ‘[‘ + line.toString() + ‘]’ : ”));

Posted on

AS3.0中三角函數的使用

先用Math.atan2()去求得圓的弧度
用法是弧度 = Math.atan2(x,y)
x與y指的是在坐標軸上形成三角型的那個點的x,y

然後再用弧度轉角度的公式去求出角度

//弧度轉角度
var arc:Number=1 //弧度
var angle=(arc*180)/Math.PI; //角度

//角度轉弧度
var angle:Number=30 //角度
var arc=angle/180*Math.PI; //弧度

另外Math.sin、Math.cos裡面要傳入的值,則是弧度
所以若我們要算sin60的值,需要這樣去代入
Math.sin(60*Math.PI/180);
那sin = 對邊/斜邊
所以要求出對邊就是 Math.sin(60*Math.PI/180) * 斜邊
其他的亦同。

語法結構:
Math.sin(數值或表達式);
Math.cos(數值或表達式);
Math.tan(數值或表達式);
Math.asin(數值或表達式);
Math.acos(數值或表達式);
Math.atan(數值或表達式);
Math.atan2(數值或表達式);
註:數值或表達式的結果值應介於-1和1之間。
範例:
myNum = Math.sin(60*Math.PI/180);
以表達式60*Math.PI/180的運算結果為參數求取正弦值並存入變量myNum中。
myNum = Math.cos(0.49);
以數值0.49為參數求取餘弦值並存入變量myNum中。
myNum = Math.tan(60*Math.PI/180);
以表達式60*Math.PI/180的運算結果為參數求取正切值並存入變量myNum中。
myNum = Math.asin(45*Math.PI/180);
以表達式45*Math.PI/180的運算結果為參數求取反正弦值並存入變量myNum中。
myNum = Math.acos(0..49);
以數值0.49為參數求取反餘弦值並存入變量myNum中。
myNum = Math.atan(30*Math.PI/180);
以表達式30*Math.PI/180的運算結果為參數求取反正切值並存入變量myNum中。
myNum = Math.atan2(30,50);
求取點50,30到X軸的角度並存入變量myNum中。

Posted on

AS3.0中製作直式書寫的方式

在as3.0中有 FTE可針對文字去測量其寬度、高度等
針對個別的文字去做處理
相關官網的說明可見此
http://help.adobe.com/en_US/ActionScript/3.0_ProgrammingAS3/WS6C0BB8ED-2805-467a-9C71-F9D757F33FB6.html

ElementFormat是定義文字的相關屬性(字型、大小、顏色等等)
然後再new一個TextElement設定文字格式和文字內容
再將其放到一個TextBlock裡面

TextBlock裡面則有許多相關的操作函數
可以對個別的文字做旋轉、定位等等
http://livedocs.adobe.com/flex/3_cn/langref/flash/text/engine/TextBlock.html
詳細的手冊說明在上面

裡面的lineRotation將角度設為九十度(TextRotation.ROTATE_90)時
文字就會呈現傳統的中文直式書寫方式呈現

下面的是將文字改為直式文字的範例程式

package {
import flash.display.Sprite;
import flash.text.engine.FontDescription;
import flash.text.engine.TextBlock;
import flash.text.engine.TextElement;
import flash.text.engine.TextLine;
import flash.text.engine.TextRotation;
import flash.text.engine.ElementFormat;

public class TextBlock_lineRotationExample extends Sprite {

public function TextBlock_lineRotationExample():void {
var s:String = “一向批判電影不會「口下留情」的大陸媒體,竟在李安導演《少年PI的奇幻漂流》內地上映後,於中國最大入口網站搜狐,罕見大讚道:『影片美輪美奐的視覺奇觀,身臨其境的3D效果。』”;

var fontDescription:FontDescription = new FontDescription(“MS Mincho”);
var format:ElementFormat = new ElementFormat();
format.fontSize = 15;
format.fontDescription = fontDescription;

var textElement:TextElement = new TextElement(s, format);
var textBlock:TextBlock = new TextBlock();
textBlock.content = textElement;
textBlock.lineRotation = TextRotation.ROTATE_90;

var linePosition:Number = this.stage.stageWidth – 120;
var previousLine:TextLine = null;

while (true) {
var textLine:TextLine = textBlock.createTextLine(
previousLine,
300);
if (textLine == null)
break;
textLine.y = 30;
textLine.x = linePosition;
linePosition -= 24;
addChild(textLine);
previousLine = textLine;
}
}
}
}

Posted on

使用Flex編譯出ios的ipa檔案

這邊提供一些我看到的教學影片及連結

1.在Windows上一步步發佈的方式

http://support.brightcove.com/en/docs/step-step-guide-publishing-apple-app-store-using-windows

2. 使用Flex編出ipa的教學

http://tv.adobe.com/watch/adc-presents/build-ios-applications-using-flex-and-flash-builder-45/

3. 怎麼在windows上產生.p12檔案

4. 在Flex裡安裝AIR SDK的方式

http://helpx.adobe.com/flash-builder/kb/error-run-debug-deploy-ios.html

http://www.flashdeveloper.co/post/10985842021/overlay-adobe-air-32-in-flash-builder-46

其實最基本的可以就依照這篇文章去做一步步的發佈設定

如果不想太快買開發者身份 也可以到google 打上fake .p12 ,下載破解檔案

就可以直接做發佈的設定了!

===================================

另外也提供不使用flex去做發佈的方式

1.安裝 adobe AIR SDK,請將以下壓縮檔,解到自己電腦任意目錄中

 http://www.adobe.com/devnet/air/air-sdk-download.html

例如,我電腦中,我解到:E:\software\AdobeAIRSDK

 

2.準備 command line 批次檔 build.bat,檔案內容如下:

 

set SDK_HOME=E:/software/AdobeAIRSDK à 換成你放 air sdk 的位置

set ADT_JAR=%SDK_HOME%/lib/adt.jar

 

set APP_NAME=HorseRacingDemo à 換成你專案的名稱,會用來找對應的 xxx.swf 與 xxx-app.xml,並發布成 xxx.ipa

set APP_ROOT_DIR=C:/Users/ben.chang/Desktop/新增資料夾 à 所有東西放置的資料夾

set BUILD_DIR=%APP_ROOT_DIR%

set APP_ROOT_FILE=%APP_NAME%.swf

set APP_DESCRIPTOR=%APP_NAME%-app.xml

set IPA_NAME=%APP_NAME%.ipa

set STORETYPE=pkcs12

set KEYSTORE=FakeCert.p12

set STOREPASS=1234

set PROVISIONING_PROFILE=Fake.mobileprovision

 

java -jar %ADT_JAR% -package -target ipa-debug -provisioning-profile %APP_ROOT_DIR%/%PROVISIONING_PROFILE% -storetype %STORETYPE% -keystore

 

%APP_ROOT_DIR%/%KEYSTORE% -storepass %STOREPASS% %APP_ROOT_DIR%/%IPA_NAME% %APP_ROOT_DIR%/%APP_DESCRIPTOR% -C %BUILD_DIR% %APP_ROOT_FILE%

 

pause

 

3.準備 xxx-app.xml

 

我的 Flash CS 5.0,設定輸出 ipad 產出的 xml 為:

<?xml version=”1.0″ encoding=”UTF-8″ standalone=”no” ?>

<application xmlns=”http://ns.adobe.com/air/application/2.0“>

<id>no-name</id>

<version>1.0</version>

<filename>?芸??1</filename>

<description/>

<name>?芸??1</name>

<copyright/>

<initialWindow>

<content>?芸??1.swf</content>

<systemChrome>standard</systemChrome>

<transparent>false</transparent>

<visible>true</visible>

<fullScreen>false</fullScreen>

<aspectRatio>portrait</aspectRatio>

<renderMode>auto</renderMode>

<autoOrients>false</autoOrients>

</initialWindow>

<icon/>

<customUpdateUI>false</customUpdateUI>

<allowBrowserInvocation>false</allowBrowserInvocation>

<iPhone>

<InfoAdditions>

      <![CDATA[<key>UIDeviceFamily</key><array><string>2</string></array>]]>

    </InfoAdditions>

</iPhone>

</application>

 

設定輸出 iphone 的 xml 為:

 

<?xml version=”1.0″ encoding=”UTF-8″ standalone=”no” ?>

<application xmlns=”http://ns.adobe.com/air/application/2.0“>

……

……

<iPhone>

 <InfoAdditions>

      <![CDATA[<key>UIDeviceFamily</key><array><string>1</string></array>]]>

    </InfoAdditions>

</iPhone>

</application>

 

設定輸出 iphone 與 ipad 的 xml 為:

<?xml version=”1.0″ encoding=”UTF-8″ standalone=”no” ?>

<application xmlns=”http://ns.adobe.com/air/application/2.0“>

……

……

<iPhone>

 <InfoAdditions>

      <![CDATA[<key>UIDeviceFamily</key><array><string>1</string><string>2</string></array>]]>

    </InfoAdditions>

</iPhone>

</application>

 

4.資料夾中準備好相關檔案:

 

l   xxx.swf

l   xxx-app.xml

l   build.bat

l   FakeCert.p12

l   Fake.mobileprovision

 

譬如,我在自己電腦桌面上開一新資料夾,如下畫面:

執行 build.bat 大約一兩分鐘 就可產出 *.ipa

 

Posted on

外行人也能學會的App企劃法

最近買了這本書:
http://buy.yahoo.com.tw/gdsale/gdbksale.asp?gdid=3639539

這本書在第一張的地方,先說出App與一般的電腦程式最大差異點在於『行動性』。
因此好的APP應具備下面幾個特質:

1. 簡單上手
2. 目的單純(一次做一件事)
3. 流暢度和穩定度

在做APP之前要先問自己下面幾個問題:

1. 為什麼要做APP而不是網站,找出做APP的意義。
2. 然後找出APP要扮演的角色,是附屬在某個服務如dropbox,或是一個獨立的服務如Line、或者是一個行銷、廣告的工具。
3. 預期這支APP可以解決什麼問題?
4. 鎖定目標族群
5. 產品所能帶來的效益

在企劃自己的APP之前,應要多去看別人的APP,以下面幾項去切入剖析

1. 是否有善用行動裝置的特性,提供一般網站無法滿足的訴求
2. 這隻APP鎖定的是那一些族群? 提供了那些主要資訊或活動?是否可以一眼吸引目標族群?所提供的功能是否符合族群功能?
3. UI是否清楚明瞭? 操作動線是否流暢?
4. 製作邏輯剖析

我們應該要多去了解市場現有的APP的狀況,或是排行榜上榜的APP遊戲,並學習用上面的觀點去剖析該APP,培養自己對於這個市場的敏銳度,從觀察中找創意。並且應善用情境想像和角色模擬,找出問題點。

在UI與動線規劃上,要了解手機動線是3D的,並且在設計上許多內容是在套入程式之後才會套入,因此程式師必須與美術設計者有較密切的溝通,才能確保美編產生的東西可以使用在程式內。在美術設計上,應該以『好用』為主要訴求。

在上架前我們則需要準備下列東西:

1. 名稱:在Iphone裡最長六個字、app store最長10個字
2. 主icon:應醒目、可表現主題
3. 截圖:以五張為限,應盡量抓可凸顯APP特色的圖
4. 文案:建議用條列式的將內容和主要功能強調出來,並加強特色介紹,讓使用者一目了然。
5. 關鍵字:盡可能把所有的關鍵字都列出來,或者也可以參考競品的APP介紹,將有用的關鍵字納入,增加APP被搜尋到的機會
6. 上架日期:若送審過後要出現在APP Store的日期

Posted on

沒有銀彈 – 軟體工程的本質性與附屬性工作

在人月神話裡,花了兩章的篇幅說明在軟體開發上,
不會有類似銀彈這種,可以快速解決開發時程延誤或發生重大錯誤的捷徑

他們提出了三個原因:

(1) 複雜性

軟體開發的複雜度與規模大小並非線性的關係,整個複雜度增加情況也會遠遠超過線性預估的結果。也因為結構上的複雜性,當軟體在擴充新功能時,難保不會產生新的副作用。程式裡的狀態難以一一列舉,也更加難以明瞭整個產品也會變的更不可靠。另外因為複雜性關係,開發時也容易遇到溝通困難、時程落後、成本超支的困難。

(2) 配合性

軟體必須配合其他的領域,例如電腦、不同語言、不同介面等等….。

(3) 易變性

1. 時常面臨修改,因為軟體是純思考的產物,有無限延展性,修改容易,也因此特別容易面臨修改
2. 成功的軟體生命周期會比硬體來的長,因此時常會需要配合硬體環境上去修改。

(4) 隱匿性:過於抽象、難以理解。

在這邊他們也提出了幾項過去曾讓軟體界有所突破的重大發展,但這些突破都是屬於附屬性的,沒辦法突破軟體工程本質上的複雜性:

(1) 高階語言:高階語言的發行的確是最強而有力的一次突破,對生產力而言至少有五倍以上的提升。並伴隨得到可靠度、簡潔性、理解力上的增益。它把和程式內涵一點關係都沒有的那一整層複雜性給去除了。

(2) 分時技術:分時技術對於程式設計師的生產力及產品品質有了重大的提升。因為分時確保了即時性,使我們得以持續保持住腦子裡對複雜的概觀。但緩慢的回復時間是附屬難題。

ps: 分時系統:作夜系統依中央處理器排程(CPU Scheduling),將中央處理器的時間切割為極小的時間片段(Time Slice)

(3) 統一的軟體開發環境:Unix和Interlisp是第一個得到廣泛使用的整合開發環境,藉由提供完整的程式庫、統一的檔案格式、管道和過濾器,以促成軟體的共用。

(4) 物件導向程式設計:抽象資料型別和階層式型別的使用。允許介面可以用次一層級的型別去做進一步的細緻化,隱藏類別裡面的實際操作,讓開發者可以在開發時專注於設計該類別的邏輯,排除掉許多附屬性困難

(5) 人工智慧:ex語音辨識、圖形辨識

(6) 專家系統:一支具有廣義推理引擎與知識庫的軟體程式,被設計成可接收輸入資料和假設條件的軟體程式,然後藉由知識庫來推導出邏輯上的結果。這項技術所帶來最重要的進步,是將應用領域的複雜性從程式中區隔出來

(7) 『自動化』程式設計:換句話說是用更高階的語言來編寫程式。未來可能我們會是用『建構』的方式來寫程式,也就是更完備的函式庫,可以讓寫程式的複雜度更加的降低。

(8)  圖形化程式設計(graphical programming):一個博班論文提出的新想法,但本書覺得要有成果應有些困難。

(9) 軟體的驗證:編輯軟體自動驗證程式的某些錯誤。例如比對資料型態、變數是否已宣告等等。

(10) 環境與工具:用來除錯、或是搜尋該類別曾被用在那些地方的開發工具。

(11) 工作站:也就是編輯所消耗的時間,若是機器的編譯時間減少,程式師能花在思考上的時間就會變多。

Posted on

人月神話讀後筆記


花了很多天終於看完了著名的專案管理聖經─『人月神話』
在此整理一下大致的重點

1. 開發一個軟體系統產品要付出的代價是一般組件程式的九倍。因為產品化是一般組件程式的三倍時間,設計整合測試又是三倍時間,這兩方面的成本計算基本上是獨立的。

2. 以成本會計為基礎的時程預估方式,使我們誤把工作量和專案進度混為一談,人月是一個危險並容易遭到誤解的迷思,因為他假設人力和工時可以互換。

在此本書裡面,提到,專案管理人員不應該把人/月這樣的標準來做為專案規劃的標準,因為當人員多起來後,整個專案的運行會需要花更多的時間在溝通、管理、協調上,人月之間的關係並非線性關係。

並且勿忽略掉新的程式師要學習上手的開發時間,以及要耗費掉的老手的教育時間。因此,在一個已經延遲的專案中增加人手,只會讓它更加的落後,這邊較建議的方式是重新安排時程、或者刪減工作。

在這一章裡,也提出建議的專案軟體時程安排方法

1/3 規劃

1/6寫程式

1/4組件測試和早期系統測試

1/4系統測試和完成所有的組件

3. 從第三章到第七章,都是在討論保有『整體概念性』的重要。

一個專案的規劃必需出由同一人之手,也就是說,一個專案不應該有兩個領導者。
我們必須選出一個能力強的人,來帶領整個專案的開發及方向,我們寧可忽略掉一些可能新奇、或很棒的想法,也必須讓整個專案都能呈現同一個設計理念。此一概念便是這本書所一直提及的整體概念性

在第三章裡,此本書提出了一個外科手術團隊的做法,來解釋該如何去達到這個整體概念性的目的。

(1) 首席程式設計師:也就是整體概念性裡所提到的做決策的主腦。負責定義功能、設計程式、測試程式並撰寫文件。
ps: 此本書也提到,真正優秀的專案管理人員,也應該要寫程式,沒有真正去撰寫一些程式的PM,是無法做好專案管理的工作的。

(2) 副手:外科醫生的分身,可以做所有首席設計師所做的事,或提出想法,但是首席設計師不一定要接納他的想法。

(3) 行政助理:幫忙處理首席程式設計師的所有庶務。一位行政助理可同時處理兩個以上團隊的工作。

(4) 文件撰寫人員、秘書(負責專案協調事宜及產品無關文件)、程式助理、測試員、語言專家、工具專家。

4. 第五章的地方,提到了第二系統效應,這個效應是指說,最容易失敗的專案,反而是我們第二個設計的系統,原因是加入了太多不相關功能。我們要慎防在設計第二個系統的時候過度設計(自律)。

5. 第六章在說意念的傳達設計必須出於同一人之手,那些有規範那些沒有應定義清楚。溝通方式包括:將定義(指規格書裡的定義)直接融入實作、開會(分為每週召開的會議、和公開大會,討論一些重大議題及無法預見的瑣碎事項)、多重實作(當規格與程式衝突時兩方都有可能要更改)、電話紀錄(現在可用email)、產品測試(專案經理最好的朋友)

6. 在第七章探討了巴別塔失敗的原因

(1) 充分的溝通十分重要

(2) 工作手冊的結構十分的重要,且每一位成員都應看到全部的文件內容

(3) 專案管理的權力結構應該要是樹狀的,也就是第三章所講的整體概念性,任何人都不能同時聽命於兩個老闆。而組織內的溝通結構則應該是網狀

7.  第八章是在討論專案時程預估要注意的點

(1) 員工只有50%的時間真正在寫程式

(2) 溝通時間應要納入估算

(3) 開發程式的類型不同以及大小之間的關係必須算進去。專案大小及費力程度大概是1.5的指數關係

8. 必須做好整體空間規劃,不單包括常駐空間的、背後有連帶關係的動作也應納入考量(ex: 記憶體分頁錯亂)
方法1. 確保大家的本事是真正通過程式設計的訓練而來
方法2.認知組件是去創造才有,每個專案都應有個手冊是專門蒐集關於佇列、搜尋、堆疊、雜湊(hashing)、Sorting的副程式且要有兩套方法,一個是用的空間最少的、一個是速度最快的。

9. 規劃軟體開發的文件:目標、產品規格、時程、預算、場地配置、組織編製圖

10. 把一次必然的失敗納入正式計劃之中(失敗是成功之母)

(1) 表格驅動技術:將設定值寫在表格檔案之中

(2) 軟體開發十分容易面臨無窮無盡的改變,因此 將改變量化,使組織利於改變

(3) 軟體測試在維護時期要用更多的資源(要做迴歸測試),也會需要進一步、退兩步,任何修改都有可能會破壞掉原有的軟體結構。

11. 第十二章在講開發工具的重要性,通常我們開發時的工具機器和最後程式要跑的目標機器是不一樣的,因此我們需要採用成熟的機器避免偶爾出現/偶爾正常的問題被忽略。程式語言的選擇也是工具的選擇之一,在這邊提到採用高階語言可以大量提高生產力。

12. 在專案開發中要如何避免錯誤的發生呢?在第十三章的地方提到了幾點重點

(1) 整體概念性的具備:也就是不同開發人員做出了彼此不協調的假設,具備了整體概念性的軟體容易使用、易於開發、也比較不容易發生錯誤。

(2) 規格審查:規格書應交給獨立的測試小組進行審查,而不應該給程式設計人員去審查

(3) 由上而下的設計方式:這是一種持續細分精製的步驟,先勾勒出粗略的工作定義和執行方案以得到主要的結果,然後做更深入的探討,看看跟我們真正要的東西有何不同。也就是把大步驟細分成幾個更小的步驟。

(4) 結構化程式設計:由Dijkstra所提出的最短路徑方式,在說由某一節點到另一個結點的最短路徑。

13. 要如何避免大災難的發生,有以下幾點:

(1) 里程碑應要明確、不模陵良可,要明顯到無法讓人自己騙自己,可以輕易查證

(2) 團隊應充滿幹勁,我們亦可提出計劃評核圖(PERT chart)或要徑時程表(critical-path schedule)來顯示什麼做完才可以做什,並告訴我們什麼事情是重要的需要先做

PERT chart
a:最樂觀時間 (Optimistic Time)為最短時間
m:最可能時間 (Most Likely Time)為適中時間
b:最悲觀時間 (Pessimistic Time)為最長時間

要徑的概念:通過網路最長的路徑,稱為要徑。若最長路徑的作業延遲了,整個專案就延遲,若要縮短專案完成時間,只要縮短要徑作業的工期即可。要完成專案,所有的路徑都必須通過。

(3) 避免隱匿不報的狀況發生:為了避免下面的人明知專案延遲卻不往上報的狀況,在組織上應降低角色衝突(老闆不應干涉部屬可以自己解決的問題),並且訂定一些審查技巧。