diff --git a/field_map.go b/field_map.go
index 2b2f285e8f9d502e6cfb0c7da8e8537c080ef5c4..0a95f2b0103440842cebac63bbf0ac24fabac3a2 100644
--- a/field_map.go
+++ b/field_map.go
@@ -2,7 +2,6 @@ package quickfix
 
 import (
 	"bytes"
-	"math"
 	"sort"
 )
 
@@ -24,50 +23,14 @@ func (t tagSort) Len() int           { return len(t.tags) }
 func (t tagSort) Swap(i, j int)      { t.tags[i], t.tags[j] = t.tags[j], t.tags[i] }
 func (t tagSort) Less(i, j int) bool { return t.compare(t.tags[i], t.tags[j]) }
 
-//in the message header, the first 3 tags in the message header must be 8,9,35
-func headerFieldOrder(i, j Tag) bool {
-	var ordering = func(t Tag) uint32 {
-		switch t {
-		case tagBeginString:
-			return 1
-		case tagBodyLength:
-			return 2
-		case tagMsgType:
-			return 3
-		}
-
-		return math.MaxUint32
-	}
-
-	orderi := ordering(i)
-	orderj := ordering(j)
-
-	switch {
-	case orderi < orderj:
-		return true
-	case orderi > orderj:
-		return false
-	}
-
-	return i < j
-}
-
-// In the body, ascending tags
+// ascending tags
 func normalFieldOrder(i, j Tag) bool { return i < j }
 
-// In the trailer, CheckSum (tag 10) must be last
-func trailerFieldOrder(i, j Tag) bool {
-	switch {
-	case i == tagCheckSum:
-		return false
-	case j == tagCheckSum:
-		return true
-	}
-
-	return i < j
+func (m *FieldMap) init() {
+	m.initWithOrdering(normalFieldOrder)
 }
 
-func (m *FieldMap) init(ordering tagOrder) {
+func (m *FieldMap) initWithOrdering(ordering tagOrder) {
 	m.tagLookup = make(map[Tag]TagValues)
 	m.tagOrder = ordering
 }
diff --git a/field_map_test.go b/field_map_test.go
index 822a64412039cefd9c7de56046e3d433307a58ba..2f73e3b58d98c2e6c8b811d0b93be4bab9e30973 100644
--- a/field_map_test.go
+++ b/field_map_test.go
@@ -5,8 +5,8 @@ import (
 )
 
 func TestFieldMap_Clear(t *testing.T) {
-	fMap := FieldMap{}
-	fMap.init(normalFieldOrder)
+	var fMap FieldMap
+	fMap.init()
 
 	fMap.SetField(1, FIXString("hello"))
 	fMap.SetField(2, FIXString("world"))
@@ -19,8 +19,8 @@ func TestFieldMap_Clear(t *testing.T) {
 }
 
 func TestFieldMap_SetAndGet(t *testing.T) {
-	fMap := FieldMap{}
-	fMap.init(normalFieldOrder)
+	var fMap FieldMap
+	fMap.init()
 
 	fMap.SetField(1, FIXString("hello"))
 	fMap.SetField(2, FIXString("world"))
@@ -57,8 +57,8 @@ func TestFieldMap_SetAndGet(t *testing.T) {
 }
 
 func TestFieldMap_Length(t *testing.T) {
-	fMap := FieldMap{}
-	fMap.init(normalFieldOrder)
+	var fMap FieldMap
+	fMap.init()
 	fMap.SetField(1, FIXString("hello"))
 	fMap.SetField(2, FIXString("world"))
 	fMap.SetField(8, FIXString("FIX.4.4"))
@@ -72,8 +72,8 @@ func TestFieldMap_Length(t *testing.T) {
 
 func TestFieldMap_Total(t *testing.T) {
 
-	fMap := FieldMap{}
-	fMap.init(normalFieldOrder)
+	var fMap FieldMap
+	fMap.init()
 	fMap.SetField(1, FIXString("hello"))
 	fMap.SetField(2, FIXString("world"))
 	fMap.SetField(8, FIXString("FIX.4.4"))
diff --git a/marshal.go b/marshal.go
index 58289693985f82b4b3c6176b2aec5d561dae7855..e4b6351b822ef5065709b1e775fcf410ef242257 100644
--- a/marshal.go
+++ b/marshal.go
@@ -105,11 +105,11 @@ func Marshal(v interface{}) Message {
 			}
 			continue
 		case "Header":
-			e.FieldMap = m.Header
+			e.FieldMap = m.Header.FieldMap
 		case "Trailer":
-			e.FieldMap = m.Trailer
+			e.FieldMap = m.Trailer.FieldMap
 		default:
-			e.FieldMap = m.Body
+			e.FieldMap = m.Body.FieldMap
 		}
 
 		e.encodeField(sf, sf.Type, reflectValue.Field(i))
diff --git a/marshal_test.go b/marshal_test.go
index 38384b6b65c1583e439108238498b3e299552bd0..4935026b8400d6647525dc8d0e57ddebd426d393 100644
--- a/marshal_test.go
+++ b/marshal_test.go
@@ -351,10 +351,10 @@ func TestMarshal_HeaderTrailer(t *testing.T) {
 		fixMsgPart quickfix.FieldMap
 		expected   []byte
 	}{
-		{quickfix.Tag(35), new(quickfix.FIXString), fixMsg.Header, []byte("0")},
-		{quickfix.Tag(49), new(quickfix.FIXString), fixMsg.Header, []byte("hello")},
-		{quickfix.Tag(112), new(quickfix.FIXString), fixMsg.Body, []byte("world")},
-		{quickfix.Tag(89), new(quickfix.FIXInt), fixMsg.Trailer, []byte("3")},
+		{quickfix.Tag(35), new(quickfix.FIXString), fixMsg.Header.FieldMap, []byte("0")},
+		{quickfix.Tag(49), new(quickfix.FIXString), fixMsg.Header.FieldMap, []byte("hello")},
+		{quickfix.Tag(112), new(quickfix.FIXString), fixMsg.Body.FieldMap, []byte("world")},
+		{quickfix.Tag(89), new(quickfix.FIXInt), fixMsg.Trailer.FieldMap, []byte("3")},
 	}
 
 	for _, test := range tests {
diff --git a/message.go b/message.go
index 40a37cdf3adee012b814c197d28013f728f7e839..b898d7ad53aa43eb499544eb5197f254dbeef21b 100644
--- a/message.go
+++ b/message.go
@@ -3,16 +3,77 @@ package quickfix
 import (
 	"bytes"
 	"fmt"
+	"math"
 	"time"
 
 	"github.com/quickfixgo/quickfix/enum"
 )
 
+//Header is first section of a FIX Message
+type Header struct{ FieldMap }
+
+//Init initializes the Header instance
+func (h *Header) Init() {
+	//in the message header, the first 3 tags in the message header must be 8,9,35
+	h.initWithOrdering(func(i, j Tag) bool {
+		var ordering = func(t Tag) uint32 {
+			switch t {
+			case tagBeginString:
+				return 1
+			case tagBodyLength:
+				return 2
+			case tagMsgType:
+				return 3
+			}
+
+			return math.MaxUint32
+		}
+
+		orderi := ordering(i)
+		orderj := ordering(j)
+
+		switch {
+		case orderi < orderj:
+			return true
+		case orderi > orderj:
+			return false
+		}
+
+		return i < j
+	})
+}
+
+//Body is the primary application section of a FIX message
+type Body struct{ FieldMap }
+
+//Init initializes the FIX message
+func (b *Body) Init() {
+	b.init()
+}
+
+//Trailer is the last section of a FIX message
+type Trailer struct{ FieldMap }
+
+//Init initializes the FIX message
+func (t *Trailer) Init() {
+	// In the trailer, CheckSum (tag 10) must be last
+	t.initWithOrdering(func(i, j Tag) bool {
+		switch {
+		case i == tagCheckSum:
+			return false
+		case j == tagCheckSum:
+			return true
+		}
+
+		return i < j
+	})
+}
+
 //Message is a FIX Message abstraction.
 type Message struct {
-	Header  FieldMap
-	Trailer FieldMap
-	Body    FieldMap
+	Header  Header
+	Trailer Trailer
+	Body    Body
 
 	//ReceiveTime is the time that this message was read from the socket connection
 	ReceiveTime time.Time
@@ -38,15 +99,11 @@ func (e parseError) Error() string { return fmt.Sprintf("error parsing message:
 
 //NewMessage returns a newly initialized Message instance
 func NewMessage() (m Message) {
-	m.Init()
-	return
-}
+	m.Header.Init()
+	m.Body.Init()
+	m.Trailer.Init()
 
-//Init initializes the Message instance
-func (m *Message) Init() {
-	m.Header.init(headerFieldOrder)
-	m.Body.init(normalFieldOrder)
-	m.Trailer.init(trailerFieldOrder)
+	return
 }
 
 //ParseMessage constructs a Message from a byte slice wrapping a FIX message.
diff --git a/repeating_group.go b/repeating_group.go
index 79fc9402d65f1a5d08c98edf14efdb3bc4914f53..f494ffce7b6931bcc108b795d852259d1bb100dc 100644
--- a/repeating_group.go
+++ b/repeating_group.go
@@ -77,7 +77,7 @@ func (f RepeatingGroup) Get(i int) Group {
 //Add appends a new group to the RepeatingGroup and returns the new Group
 func (f *RepeatingGroup) Add() Group {
 	var g Group
-	g.init(f.groupTagOrder())
+	g.initWithOrdering(f.groupTagOrder())
 
 	f.groups = append(f.groups, g)
 	return g
@@ -157,7 +157,7 @@ func (f *RepeatingGroup) Read(tv TagValues) (TagValues, error) {
 	tv = tv[1:cap(tv)]
 	tagOrdering := f.groupTagOrder()
 	var group Group
-	group.init(tagOrdering)
+	group.initWithOrdering(tagOrdering)
 	for len(tv) > 0 {
 		field, ok := f.findItemInGroupTemplate(tv[0].tag)
 		if !ok {
@@ -171,7 +171,7 @@ func (f *RepeatingGroup) Read(tv TagValues) (TagValues, error) {
 
 		if f.isDelimiter(field.Tag()) {
 			group = Group{}
-			group.init(tagOrdering)
+			group.initWithOrdering(tagOrdering)
 
 			f.groups = append(f.groups, group)
 		}
diff --git a/session.go b/session.go
index e64238d793ed294dcfa36c25d01fd9bc12ce27f4..dbaf6d8f3fb4413b01f6a35cfcf1321aaa8a5dcf 100644
--- a/session.go
+++ b/session.go
@@ -2,11 +2,12 @@ package quickfix
 
 import (
 	"fmt"
+	"sync"
+	"time"
+
 	"github.com/quickfixgo/quickfix/config"
 	"github.com/quickfixgo/quickfix/datadictionary"
 	"github.com/quickfixgo/quickfix/enum"
-	"sync"
-	"time"
 )
 
 //The Session is the primary FIX abstraction for message communication
@@ -152,7 +153,7 @@ func (s *session) onDisconnect() {
 	s.log.OnEvent("Disconnected")
 }
 
-func (s *session) insertSendingTime(header FieldMap) {
+func (s *session) insertSendingTime(header Header) {
 	sendingTime := time.Now().UTC()
 
 	if s.sessionID.BeginString >= enum.BeginStringFIX42 {
diff --git a/session_test.go b/session_test.go
index 3989fc3703274cea77f4706bb9774415644be8e6..15d4db287b77409aaabb6296d8a94c855b66ae24 100644
--- a/session_test.go
+++ b/session_test.go
@@ -1,14 +1,14 @@
 package quickfix
 
 import (
-	"github.com/quickfixgo/quickfix/enum"
 	"testing"
 	"time"
+
+	"github.com/quickfixgo/quickfix/enum"
 )
 
 func buildMessage() Message {
-	builder := Message{}
-	builder.Init()
+	builder := NewMessage()
 	builder.Header.SetField(tagBeginString, FIXString(enum.BeginStringFIX40))
 	builder.Header.SetField(tagMsgType, FIXString("D"))
 	return builder
diff --git a/unmarshal.go b/unmarshal.go
index 92093f82013431fb9696db1cd63fdce63b75d4c0..6b705a78b6b2cb47838225f2ed079d23ba8f1eb6 100644
--- a/unmarshal.go
+++ b/unmarshal.go
@@ -124,11 +124,11 @@ func Unmarshal(m Message, v interface{}) MessageRejectError {
 		case "FIXMsgType":
 			continue
 		case "Header":
-			d.FieldMap = m.Header
+			d.FieldMap = m.Header.FieldMap
 		case "Trailer":
-			d.FieldMap = m.Trailer
+			d.FieldMap = m.Trailer.FieldMap
 		default:
-			d.FieldMap = m.Body
+			d.FieldMap = m.Body.FieldMap
 		}
 
 		if err := d.decodeField(sf, sf.Type, sv); err != nil {
diff --git a/validation.go b/validation.go
index 6a9029021f0c97b102d8118b0d50c549e305051d..b71a9b54113b5a63a1c3c2ebe17c2015ea6cffb3 100644
--- a/validation.go
+++ b/validation.go
@@ -242,15 +242,15 @@ func validateOrder(msg Message) MessageRejectError {
 }
 
 func validateRequired(transportDD *datadictionary.DataDictionary, appDD *datadictionary.DataDictionary, msgType string, message Message) MessageRejectError {
-	if err := validateRequiredFieldMap(message, transportDD.Header.RequiredTags, message.Header); err != nil {
+	if err := validateRequiredFieldMap(message, transportDD.Header.RequiredTags, message.Header.FieldMap); err != nil {
 		return err
 	}
 
-	if err := validateRequiredFieldMap(message, appDD.Messages[msgType].RequiredTags, message.Body); err != nil {
+	if err := validateRequiredFieldMap(message, appDD.Messages[msgType].RequiredTags, message.Body.FieldMap); err != nil {
 		return err
 	}
 
-	if err := validateRequiredFieldMap(message, transportDD.Trailer.RequiredTags, message.Trailer); err != nil {
+	if err := validateRequiredFieldMap(message, transportDD.Trailer.RequiredTags, message.Trailer.FieldMap); err != nil {
 		return err
 	}